using GameData.Helper; using GameData.Model; using GameData.Repository; using GameModel.Settings; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http.Headers; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Web; namespace GameData { public sealed class ApiClient : IDisposable { private class WrapperArray { public T[] Data { get; set; } } private class WrapperSingle { public T Data { get; set; } } private readonly HttpClient client; private readonly ILogger _logger; private readonly AppSettings _appSettings; private readonly string Api; public ApiClient(AppSettings appSettings, ILogger logger) { _logger = logger; _appSettings = appSettings; client = new HttpClient { Timeout = TimeSpan.FromMinutes(1) }; client.DefaultRequestHeaders .Accept .Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders .Authorization = new AuthenticationHeaderValue("Bearer", _appSettings.ApiToken); //client.DefaultRequestHeaders.Add("Api-AppInfo", "KrahApp;" + Assembly.GetExecutingAssembly().GetName().Version.ToString()); Api = _appSettings.ApiBaseUrl; if (!Api.EndsWith("/")) { Api += "/"; } } public void Dispose() { client.Dispose(); } public string UrlEncode(string s) { return HttpUtility.UrlEncode(s); } private string GetFullUrl(string url) { if (url[0].Equals('/')) { url = url.Remove(0, 1); } url = Api + url; return url; } private HttpRequestMessage GetHttpRequestMessage(HttpMethod method, string serviceUrl, object payload = null) { StringContent content = null; if (payload != null) { var payloadString = LowercaseJsonSerializer.SerializeObject(payload); content = new StringContent(payloadString, Encoding.UTF8, "application/json"); } var url = serviceUrl; if (!serviceUrl.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) { url = GetFullUrl(serviceUrl); } var res = new HttpRequestMessage { Content = content, Method = method, RequestUri = new Uri(url), }; //res.Headers.Add("Authorization: Bearer", _apiKey); return res; } public async Task DownloadFile(string serviceUrl, string targetFile) { var res = false; try { var request = GetHttpRequestMessage(HttpMethod.Get, serviceUrl); request.Headers.Add("Accept", "application/json"); request.Headers.Add("Accept", "application/octet-stream"); request.Headers.Add("Accept", "file/download"); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { using (var responseStream = await response.Content.ReadAsStreamAsync()) { using (var fileStream = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true)) { await responseStream.CopyToAsync(fileStream); res = true; } } } else { var errorResult = await response.Content.ReadAsStringAsync(); _logger.LogError("error downloading from service '{service}' with code '{statuscode}' - Result: '{result}', TargetFile: '{payload}'", serviceUrl, response.StatusCode, errorResult, targetFile); } } catch (Exception ex) { _logger.LogError(ex, "error at DownloadFile"); } return res; } /// /// Create an item /// https://docs.directus.io/reference/items.html#create-an-item /// /// /// /// /// /// public async Task Post(object payload, string serviceUrl, bool suppressExceptions = false) { T res = default; try { var response = await client.SendAsync(GetHttpRequestMessage(HttpMethod.Post, serviceUrl, payload)); if (response.IsSuccessStatusCode) { using (var responseStream = response.Content.ReadAsStream()) { using (var streamReader = new StreamReader(responseStream)) { using (var jsonTextReader = new JsonTextReader(streamReader)) { var serializer = new JsonSerializer(); var wrapper = serializer.Deserialize>(jsonTextReader); res = wrapper.Data; } } } } else { var errorResult = await response.Content.ReadAsStringAsync(); _logger.LogError("error posting to service '{service}' with code '{statuscode}' - Result: '{result}', Payload: '{payload}'", serviceUrl, response.StatusCode, errorResult, JsonConvert.SerializeObject(payload)); } } catch (Exception ex) { _logger.LogError(ex, "error at post"); if (!suppressExceptions) { throw ex; } } return res; } public async Task Delete(object payload, string serviceUrl, bool suppressExceptions = true) { try { var response = await client.SendAsync(GetHttpRequestMessage(HttpMethod.Delete, serviceUrl, payload)); if (response.IsSuccessStatusCode) { //using (var responseStream = await response.Content.ReadAsStreamAsync()) //{ // using (var streamReader = new StreamReader(responseStream)) // { // using (var jsonTextReader = new JsonTextReader(streamReader)) // { // var serializer = new JsonSerializer(); // res = serializer.Deserialize(jsonTextReader); // } // } //} } else { var errorResult = await response.Content.ReadAsStringAsync(); _logger.LogError("error deleting to service '{service}' with code '{statuscode}' - Result: '{result}', Payload: '{payload}'", serviceUrl, response.StatusCode, errorResult, JsonConvert.SerializeObject(payload)); } } catch (Exception ex) { _logger.LogError(ex, "error at Delete"); if (!suppressExceptions) { throw ex; } } //return res; } public async Task Get(string serviceUrl, bool suppressExceptions = false) { WrapperArray res = default; try { _logger.LogDebug($"calling service url {serviceUrl}"); var response = await client.SendAsync(GetHttpRequestMessage(HttpMethod.Get, serviceUrl)); if (response.IsSuccessStatusCode) { using (var responseStream = response.Content.ReadAsStream()) { using (var streamReader = new StreamReader(responseStream)) { string content; if (typeof(T).Equals(typeof(string))) { content = streamReader.ReadToEnd(); res = (WrapperArray)Convert.ChangeType(content, typeof(T)); } else { using (var jsonTextReader = new JsonTextReader(streamReader)) { var serializer = new JsonSerializer(); res = serializer.Deserialize>(jsonTextReader); } } } } } else { var errorResult = await response.Content.ReadAsStringAsync(); _logger.LogError("error getting from service '{service}' with code '{statuscode}' - Result: '{result}'", serviceUrl, response.StatusCode, errorResult); } } catch (Exception ex) { _logger.LogError(ex, "error at Get"); if (!suppressExceptions) { throw ex; } } return res.Data; } public async Task GetSingle(string serviceUrl, bool suppressExceptions = false) { WrapperSingle res = default; try { _logger.LogDebug($"calling service url {serviceUrl}"); var response = await client.SendAsync(GetHttpRequestMessage(HttpMethod.Get, serviceUrl)); if (response.IsSuccessStatusCode) { using (var responseStream = response.Content.ReadAsStream()) { using (var streamReader = new StreamReader(responseStream)) { string content; if (typeof(T).Equals(typeof(string))) { content = streamReader.ReadToEnd(); res = (WrapperSingle)Convert.ChangeType(content, typeof(T)); } else { using (var jsonTextReader = new JsonTextReader(streamReader)) { var serializer = new JsonSerializer(); res = serializer.Deserialize>(jsonTextReader); } } } } } else { var errorResult = await response.Content.ReadAsStringAsync(); _logger.LogError("error getting from service '{service}' with code '{statuscode}' - Result: '{result}'", serviceUrl, response.StatusCode, errorResult); return await Task.FromResult(default(T)); } } catch (Exception ex) { _logger.LogError(ex, "error at Get"); if (!suppressExceptions) { throw ex; } } return res.Data; } internal async Task Put(object payload, string serviceUrl, bool suppressExceptions = false) { T res = default; try { var response = await client.SendAsync(GetHttpRequestMessage(HttpMethod.Post, serviceUrl, payload)); if (response.IsSuccessStatusCode) { using (var responseStream = response.Content.ReadAsStream()) { using (var streamReader = new StreamReader(responseStream)) { using (var jsonTextReader = new JsonTextReader(streamReader)) { var serializer = new JsonSerializer(); var wrapper = serializer.Deserialize>(jsonTextReader); res = wrapper.Data; } } } } else { var errorResult = await response.Content.ReadAsStringAsync(); _logger.LogError("error posting to service '{service}' with code '{statuscode}' - Result: '{result}', Payload: '{payload}'", serviceUrl, response.StatusCode, errorResult, JsonConvert.SerializeObject(payload)); } } catch (Exception ex) { _logger.LogError(ex, "error at post"); if (!suppressExceptions) { throw ex; } } } } }