70 lines
2.5 KiB
C#
70 lines
2.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.WebUtilities;
|
|
using Microsoft.Extensions.Caching.Memory;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace Website.Data {
|
|
public abstract class ApiClient {
|
|
private readonly HttpClient _client;
|
|
private readonly IMemoryCache _cache;
|
|
private readonly CacheDurations _cacheDurations;
|
|
|
|
protected ApiClient(HttpClient client, IMemoryCache cache, CacheDurations cacheDurations) {
|
|
_client = client;
|
|
_cache = cache;
|
|
_cacheDurations = cacheDurations;
|
|
}
|
|
|
|
private IDictionary<string, string> ParseQueryParameters(object query) {
|
|
var type = query.GetType();
|
|
var props = type.GetProperties();
|
|
return props.ToDictionary(info => info.Name, info => info.GetValue(query, null).ToString());
|
|
}
|
|
|
|
private async Task<TResult> DoCachedCall<TResult>(HttpMethod method, string callerName, string url, Func<Task<TResult>> call) {
|
|
if (method == HttpMethod.Post)
|
|
return await call();
|
|
|
|
var baseKey = GetType().Name + ":" + callerName;
|
|
var key = baseKey + "/" + url;
|
|
|
|
return await _cache.GetOrCreate(key, async entry => {
|
|
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(_cacheDurations[baseKey]);
|
|
return await call();
|
|
});
|
|
}
|
|
|
|
private async Task<T> Send<T>(HttpMethod method, string url, object query, string callerName, HttpContent content = null) {
|
|
if (query != null)
|
|
url = QueryHelpers.AddQueryString(url, ParseQueryParameters(query));
|
|
|
|
return await DoCachedCall(method, callerName, url, async () => {
|
|
using var httpRequest = new HttpRequestMessage(method, url) { Content = content };
|
|
var response = await _client.SendAsync(httpRequest);
|
|
|
|
if (!response.IsSuccessStatusCode)
|
|
throw new ApiCallException(response);
|
|
|
|
var json = await response.Content.ReadAsStringAsync();
|
|
return JsonConvert.DeserializeObject<T>(json);
|
|
});
|
|
}
|
|
|
|
protected async Task<T> Post<T>(string url, object value, object query = null, [CallerMemberName] string callerName = "") {
|
|
var json = JsonConvert.SerializeObject(value);
|
|
using var requestBody = new StringContent(json, Encoding.UTF8, "application/json");
|
|
return await Send<T>(HttpMethod.Post, url, query, callerName, requestBody);
|
|
}
|
|
|
|
protected async Task<T> Get<T>(string url, object query = null, [CallerMemberName] string callerName = "") {
|
|
return await Send<T>(HttpMethod.Get, url, query, callerName);
|
|
}
|
|
|
|
}
|
|
}
|