using Blazored.LocalStorage; using System.Globalization; using System.Net.Http.Json; using System.Net; using decePubClient.Models; namespace decePubClient.Services { public interface IHttpService { Task Get(string uri, object payload = default, string?[] queryParams = default); Task GetAnon(string uri, object payload = default, string?[] queryParams = default); Task Post(string uri, object payload = default); Task PostAnon(string uri, object payload = default); Task Delete(string uri, string?[] queryParams = default, object payload = default); } public class HttpService : IHttpService { readonly IHttpClientFactory HttpClientFactory; readonly TokenAuthStateProvider AuthStateProvider; readonly ILogger Logger; readonly ILocalStorageService Storage; readonly IStorage DbStorage; public HttpService( IHttpClientFactory httpClientFactory, TokenAuthStateProvider authStateProvider, ILogger logger, ILocalStorageService storage, IStorage dbStorage) { HttpClientFactory = httpClientFactory; AuthStateProvider = authStateProvider; Logger = logger; Storage = storage; DbStorage = dbStorage; } public async Task Get(string uri, object payload = default, string?[] queryParams = default) { try { uri = $"{CultureInfo.DefaultThreadCurrentCulture.TwoLetterISOLanguageName}/{uri}"; var request = default(HttpRequestMessage); if (queryParams != null) request = new(HttpMethod.Get, string.Join('?', uri, string.Join('&', queryParams))); else request = new(HttpMethod.Get, uri); if (payload != null) request.Content = JsonContent.Create(payload); return await SendRequest(request); } catch (Exception ex) { Logger.LogError(ex, $"{nameof(Get)}:{uri}"); await DbStorage.AddLog(ex, $"{nameof(Get)}:{uri}"); return new(HttpStatusCode.ServiceUnavailable); } } public async Task Post(string uri, object payload = default) { try { uri = $"{CultureInfo.DefaultThreadCurrentCulture.TwoLetterISOLanguageName}/{uri}"; var request = new HttpRequestMessage(HttpMethod.Post, uri) { Content = JsonContent.Create(payload) }; return await SendRequest(request); } catch (Exception ex) { Logger.LogError(ex, $"{nameof(Post)}:{uri}"); await DbStorage.AddLog(ex, $"{nameof(Post)}:{uri}"); return new(HttpStatusCode.ServiceUnavailable); } } public async Task GetAnon(string uri, object payload = default, string?[] queryParams = default) { try { uri = $"{CultureInfo.DefaultThreadCurrentCulture.TwoLetterISOLanguageName}/{uri}"; var request = default(HttpRequestMessage); if (queryParams != null) request = new(HttpMethod.Get, string.Join('?', uri, string.Join('&', queryParams))); else request = new(HttpMethod.Get, uri); if (payload != null) request.Content = JsonContent.Create(payload); return await SendAnonRequest(request); } catch (Exception ex) { Logger.LogError(ex, $"{nameof(GetAnon)}:{uri}"); await DbStorage.AddLog(ex, $"{nameof(GetAnon)}:{uri}"); return new(HttpStatusCode.ServiceUnavailable); } } public async Task PostAnon(string uri, object payload = default) { try { uri = $"{CultureInfo.DefaultThreadCurrentCulture.TwoLetterISOLanguageName}/{uri}"; var request = new HttpRequestMessage(HttpMethod.Post, uri) { Content = JsonContent.Create(payload) }; return await SendAnonRequest(request); } catch (Exception ex) { Logger.LogError(ex, $"{nameof(PostAnon)}:{uri}"); await DbStorage.AddLog(ex, $"{nameof(PostAnon)}:{uri}"); return new(HttpStatusCode.ServiceUnavailable); } } public async Task Delete(string uri, string?[] queryParams = default, object payload = default) { try { uri = $"{CultureInfo.DefaultThreadCurrentCulture.TwoLetterISOLanguageName}/{uri}"; var request = default(HttpRequestMessage); if (queryParams != null) request = new(HttpMethod.Delete, string.Join('?', uri, string.Join('&', queryParams))); else request = new(HttpMethod.Delete, uri); if (payload != null) request.Content = JsonContent.Create(payload); return await SendRequest(request); } catch (Exception ex) { Logger.LogError(ex, $"{nameof(Delete)}:{uri}"); await DbStorage.AddLog(ex, $"{nameof(Delete)}:{uri}"); return new(HttpStatusCode.ServiceUnavailable); } } // helper methods async Task SendRequest(HttpRequestMessage request) { try { var authData = await Storage.GetItemAsync(nameof(AuthData)); var isApiUrl = !request.RequestUri?.IsAbsoluteUri; if (isApiUrl.HasValue && isApiUrl.Value) request.Headers.Authorization = new("Bearer", authData.Token); var response = await HttpClientFactory.CreateClient().SendAsync(request); if (response.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden) { Logger.LogWarning($"{nameof(SendRequest)}:401/403:{request.RequestUri?.OriginalString}:{await response.Content.ReadAsStringAsync()}"); await DbStorage.AddLog($"{nameof(SendRequest)}:401/403:{request.RequestUri?.OriginalString}:{await response.Content.ReadAsStringAsync()}", $"{nameof(SendRequest)}:{request.RequestUri?.OriginalString}"); await AuthStateProvider.LogoutAsync(); } return response; } catch (Exception ex) { Logger.LogError(ex, $"{nameof(SendRequest)}:{request.RequestUri?.OriginalString}"); await DbStorage.AddLog(ex, $"{nameof(SendRequest)}:{request.RequestUri?.OriginalString}"); return new(HttpStatusCode.ServiceUnavailable); } } async Task SendAnonRequest(HttpRequestMessage request) { try { var authData = await Storage.GetItemAsync(nameof(AuthData)); if (!string.IsNullOrEmpty(authData?.Token)) request.Headers.Authorization = new("Bearer", authData.Token); var response = await HttpClientFactory.CreateClient().SendAsync(request); return response; } catch (Exception ex) { Logger.LogError(ex, $"{nameof(SendAnonRequest)}:{request.RequestUri?.OriginalString}"); await DbStorage.AddLog(ex, $"{nameof(SendAnonRequest)}:{request.RequestUri?.OriginalString}"); return new(HttpStatusCode.ServiceUnavailable); } } } }