using Microsoft.Extensions.Logging; using System.IO; using System.Net.Http.Headers; using System.Text; using System.Text.Json; namespace JSMR.Infrastructure.Http; public abstract class ApiClient(IHttpService http, ILogger logger, JsonSerializerOptions? json = null) { protected async Task GetJsonAsync(string url, CancellationToken cancellationToken = default) { string response = await http.GetStringAsync(url, cancellationToken); return JsonSerializer.Deserialize(response, json) ?? throw new InvalidOperationException($"Failed to deserialize JSON to {typeof(T).Name} from {url}."); } //protected async Task GetJsonAsync( // string url, // Action? configureHeaders = null, // CancellationToken ct = default // ) //{ // using var req = new HttpRequestMessage(HttpMethod.Get, url); // configureHeaders?.Invoke(req.Headers); // LogRequest(req); // using var res = await http.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, ct).ConfigureAwait(false); // await EnsureSuccess(res).ConfigureAwait(false); // var stream = await res.Content.ReadAsStreamAsync(ct).ConfigureAwait(false); // var model = await JsonSerializer.DeserializeAsync(stream, json, ct).ConfigureAwait(false) // ?? throw new InvalidOperationException($"Failed to deserialize JSON to {typeof(T).Name} from {url}."); // return model; //} //protected async Task PostJsonAsync( // string url, // TRequest payload, // Action? configureHeaders = null, // CancellationToken ct = default) //{ // var content = new StringContent(JsonSerializer.Serialize(payload, json), Encoding.UTF8, "application/json"); // using var req = new HttpRequestMessage(HttpMethod.Post, url) { Content = content }; // configureHeaders?.Invoke(req.Headers); // LogRequest(req); // using var res = await http.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, ct).ConfigureAwait(false); // await EnsureSuccess(res).ConfigureAwait(false); // var stream = await res.Content.ReadAsStreamAsync(ct).ConfigureAwait(false); // var model = await JsonSerializer.DeserializeAsync(stream, json, ct).ConfigureAwait(false) // ?? throw new InvalidOperationException($"Failed to deserialize JSON to {typeof(TResponse).Name} from {url}."); // return model; //} //protected virtual void LogRequest(HttpRequestMessage req) // => logger.LogDebug("HTTP {Method} {Uri}", req.Method, req.RequestUri); //protected virtual void LogFailure(HttpResponseMessage res, string body) // => logger.LogWarning("HTTP {Status} for {Uri}. Body: {Body}", (int)res.StatusCode, res.RequestMessage?.RequestUri, Truncate(body, 500)); //protected static string Truncate(string s, int max) => s.Length <= max ? s : s[..max] + "…"; //protected async Task EnsureSuccess(HttpResponseMessage res) //{ // if (res.IsSuccessStatusCode) return; // string body; // try { body = await res.Content.ReadAsStringAsync().ConfigureAwait(false); } // catch { body = ""; } // LogFailure(res, body); // Throw a richer exception(you can customize per API) // throw new HttpRequestException( // $"Request to {res.RequestMessage?.RequestUri} failed: {(int)res.StatusCode} {res.ReasonPhrase}. Body: {Truncate(body, 1000)}", // null, // res.StatusCode); //} }