This commit is contained in:
@@ -6,19 +6,346 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace AyaNovaQBI
|
||||
{
|
||||
internal class util
|
||||
{
|
||||
#region API stuff
|
||||
public const string TEST_ROUTE = "notify/hello";
|
||||
public const string API_BASE_ROUTE = "api/v8/";
|
||||
private const int MAX_TRIES = 3;//max times to retry an api call before giving up
|
||||
private const int API_RETRY_DELAY = 3000;//pause in ms before retrying api call
|
||||
public static int HTTPCLIENT_TIMEOUT_SECONDS = 100;//changed by the setting in ops anyway, just a in-case sensible default here
|
||||
public static HttpClient client = null;
|
||||
internal static string SERVER_URL { get; set; } = Properties.Settings.Default.serverurl;
|
||||
|
||||
//url once known to be good
|
||||
internal static string ApiBaseUrl { get; set; }
|
||||
//auth processes url for api and this is the best guess as to the client url to use for notification / help links etc
|
||||
internal static string GuessClientUrl { get; set; }
|
||||
|
||||
internal static string JWT { get; set; }
|
||||
|
||||
|
||||
|
||||
public static void InitClient()
|
||||
{
|
||||
if (client != null)
|
||||
{
|
||||
client.Dispose();
|
||||
client = null;
|
||||
}
|
||||
client = new HttpClient();
|
||||
client.Timeout = TimeSpan.FromSeconds(HTTPCLIENT_TIMEOUT_SECONDS);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only a return value of "OK" is ok
|
||||
/// </summary>
|
||||
/// <param name="serverUrl"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> InitAndConfirmAddressAsync(string serverUrl)
|
||||
{
|
||||
ApiBaseUrl = serverUrl;
|
||||
InitClient();
|
||||
try
|
||||
{
|
||||
// TimeSpan tsDefault = client.Timeout;
|
||||
// client.Timeout = new TimeSpan(0, 0, 20);
|
||||
HttpResponseMessage response = await client.GetAsync(serverUrl + TEST_ROUTE);
|
||||
// client.Timeout = tsDefault;
|
||||
if (response.IsSuccessStatusCode)
|
||||
return "OK";
|
||||
else
|
||||
return "Failed: " + response.StatusCode.ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
while (ex.InnerException != null)
|
||||
ex = ex.InnerException;
|
||||
return "Failed exception: \r\n" + ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async static Task<bool> AuthenticateAsync(string login, string password = null)
|
||||
{
|
||||
InitClient();
|
||||
|
||||
if (password == null)
|
||||
password = login;
|
||||
|
||||
dynamic creds = new JObject();
|
||||
creds.login = login;
|
||||
creds.password = password;
|
||||
|
||||
ApiResponse a = await PostAsync("auth", creds.ToString());
|
||||
|
||||
if (a.HttpResponse.IsSuccessStatusCode)
|
||||
{
|
||||
JWT = a.ObjectResponse["data"]["token"].Value<string>();
|
||||
//Must be *the* SuperUser to continue:
|
||||
a = await GetAsync("user/amsu");
|
||||
var IsSuperUser = a.ObjectResponse["data"].Value<bool>();
|
||||
if (!IsSuperUser)
|
||||
{
|
||||
JWT = string.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public async static Task<ApiResponse> GetAsync(string route)
|
||||
{
|
||||
Exception FirstException = null;
|
||||
|
||||
for (int x = 0; x < MAX_TRIES; x++)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await TryGetAsync(route);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (FirstException == null)
|
||||
FirstException = ex;
|
||||
}
|
||||
await Task.Delay(API_RETRY_DELAY);
|
||||
}
|
||||
|
||||
//no luck re-throw the exception
|
||||
throw new Exception("API call failed after " + MAX_TRIES.ToString() + " attempts", FirstException);
|
||||
}
|
||||
|
||||
private async static Task<ApiResponse> TryGetAsync(string route)
|
||||
{
|
||||
var requestMessage = new HttpRequestMessage(HttpMethod.Get, ApiBaseUrl + route);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(JWT))
|
||||
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", JWT);
|
||||
|
||||
HttpResponseMessage response = null;
|
||||
try
|
||||
{
|
||||
response = await client.SendAsync(requestMessage);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
var Err = ex.Message;
|
||||
var InnerErr = "";
|
||||
if (ex.InnerException != null)
|
||||
InnerErr = ex.InnerException.Message;
|
||||
throw new Exception("GET error, route: " + route + "\r\nError:" + Err + "\r\nInner error:" + InnerErr + "\r\nStack:" + ex.StackTrace);
|
||||
}
|
||||
|
||||
|
||||
var responseAsString = await response.Content.ReadAsStringAsync();
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
throw new Exception("GET error, code: " + (int)response.StatusCode + ", route: " + route + "\r\n" + responseAsString + "\r\n" + response.ReasonPhrase);
|
||||
}
|
||||
else
|
||||
return new ApiResponse() { HttpResponse = response, ObjectResponse = Parse(responseAsString) };
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public async static Task<ApiResponse> PostAsync(string route, dynamic d)
|
||||
{
|
||||
Exception FirstException = null;
|
||||
|
||||
for (int x = 0; x < MAX_TRIES; x++)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await TryPostAsync(route, d.ToString(Newtonsoft.Json.Formatting.None));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (FirstException == null)
|
||||
FirstException = ex;
|
||||
}
|
||||
await Task.Delay(API_RETRY_DELAY);
|
||||
}
|
||||
|
||||
//no luck re-throw the exception
|
||||
throw new Exception("API call failed after " + MAX_TRIES.ToString() + " attempts", FirstException);
|
||||
}
|
||||
|
||||
public async static Task<ApiResponse> PostAsync(string route, string s = null)
|
||||
{
|
||||
Exception FirstException = null;
|
||||
|
||||
for (int x = 0; x < MAX_TRIES; x++)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await TryPostAsync(route, s);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (FirstException == null)
|
||||
FirstException = ex;
|
||||
}
|
||||
await Task.Delay(API_RETRY_DELAY);
|
||||
}
|
||||
|
||||
//no luck re-throw the exception
|
||||
throw new Exception("API call failed after " + MAX_TRIES.ToString() + " attempts", FirstException);
|
||||
}
|
||||
|
||||
|
||||
private async static Task<ApiResponse> TryPostAsync(string route, string postJson = null)
|
||||
{
|
||||
|
||||
var requestMessage = new HttpRequestMessage(HttpMethod.Post, ApiBaseUrl + route);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(JWT))
|
||||
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", JWT);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(postJson))
|
||||
requestMessage.Content = new StringContent(postJson, System.Text.Encoding.UTF8, "application/json");
|
||||
HttpResponseMessage response = null;
|
||||
try
|
||||
{
|
||||
response = await client.SendAsync(requestMessage);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
var Err = ex.Message;
|
||||
var InnerErr = "";
|
||||
if (ex.InnerException != null)
|
||||
InnerErr = ex.InnerException.Message;
|
||||
throw new Exception("POST error, route: " + route + "\r\nError:" + Err + "\r\nInner error:" + InnerErr + "\r\nStack:" + ex.StackTrace + "\r\nPOSTED OBJECT:\r\n" + postJson);
|
||||
}
|
||||
var responseAsString = await response.Content.ReadAsStringAsync();
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(postJson))
|
||||
postJson = "n/a";
|
||||
throw new Exception("POST error, code: " + (int)response.StatusCode + ", route: " + route + "\r\n" + responseAsString + "\r\n" + response.ReasonPhrase + "\r\nPOSTED OBJECT:\r\n" + postJson);
|
||||
}
|
||||
else
|
||||
return new ApiResponse() { HttpResponse = response, ObjectResponse = Parse(responseAsString) };
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public async static Task<ApiResponse> PutAsync(string route, dynamic d)
|
||||
{
|
||||
Exception FirstException = null;
|
||||
|
||||
for (int x = 0; x < MAX_TRIES; x++)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await TryPutAsync(route, d.ToString(Newtonsoft.Json.Formatting.None));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (FirstException == null)
|
||||
FirstException = ex;
|
||||
}
|
||||
await Task.Delay(API_RETRY_DELAY);
|
||||
}
|
||||
|
||||
//no luck re-throw the exception
|
||||
throw new Exception("API call failed after " + MAX_TRIES.ToString() + " attempts", FirstException);
|
||||
}
|
||||
|
||||
public async static Task<ApiResponse> PutAsync(string route)
|
||||
{
|
||||
Exception FirstException = null;
|
||||
|
||||
for (int x = 0; x < MAX_TRIES; x++)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await TryPutAsync(route);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (FirstException == null)
|
||||
FirstException = ex;
|
||||
}
|
||||
await Task.Delay(API_RETRY_DELAY);
|
||||
}
|
||||
|
||||
//no luck re-throw the exception
|
||||
throw new Exception("API call failed after " + MAX_TRIES.ToString() + " attempts", FirstException);
|
||||
}
|
||||
|
||||
public async static Task<ApiResponse> TryPutAsync(string route, string putJson = null)
|
||||
{
|
||||
var requestMessage = new HttpRequestMessage(HttpMethod.Put, ApiBaseUrl + route);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(JWT))
|
||||
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", JWT);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(putJson))
|
||||
requestMessage.Content = new StringContent(putJson, System.Text.Encoding.UTF8, "application/json");
|
||||
HttpResponseMessage response = null;
|
||||
try
|
||||
{
|
||||
response = await client.SendAsync(requestMessage);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
var Err = ex.Message;
|
||||
var InnerErr = "";
|
||||
if (ex.InnerException != null)
|
||||
InnerErr = ex.InnerException.Message;
|
||||
throw new Exception("PUT error, route: " + route + "\r\nError:" + Err + "\r\nInner error:" + InnerErr + "\r\nStack:" + ex.StackTrace + "\r\nPOSTED OBJECT:\r\n" + putJson);
|
||||
}
|
||||
var responseAsString = await response.Content.ReadAsStringAsync();
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(putJson))
|
||||
putJson = "n/a";
|
||||
throw new Exception("PUT error, code: " + (int)response.StatusCode + ", route: " + route + "\r\n" + responseAsString + "\r\n" + response.ReasonPhrase + "\r\nPUT OBJECT:\r\n" + putJson);
|
||||
}
|
||||
else
|
||||
return new ApiResponse() { HttpResponse = response, ObjectResponse = Parse(responseAsString) };
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class ApiResponse
|
||||
{
|
||||
public HttpResponseMessage HttpResponse { get; set; }
|
||||
public JObject ObjectResponse { get; set; }
|
||||
public string CompactResponse
|
||||
{
|
||||
get
|
||||
{
|
||||
return ObjectResponse.ToString(Newtonsoft.Json.Formatting.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region QB STUFF
|
||||
public static List<InvoiceableItem> GetInvoiceableItems()
|
||||
{
|
||||
var random = new Random();
|
||||
@@ -66,7 +393,7 @@ namespace AyaNovaQBI
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user