2025-06-22 10:40:42 +03:00
|
|
|
using System.Diagnostics.Contracts;
|
2024-12-22 16:38:47 +03:00
|
|
|
using System.Globalization;
|
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Text.Json;
|
2025-05-05 20:43:28 +03:00
|
|
|
using Nebula.Shared.Services.Logging;
|
2025-01-05 17:05:23 +03:00
|
|
|
using Nebula.Shared.Utils;
|
2024-12-22 16:38:47 +03:00
|
|
|
|
2025-01-05 17:05:23 +03:00
|
|
|
namespace Nebula.Shared.Services;
|
2024-12-22 16:38:47 +03:00
|
|
|
|
|
|
|
|
[ServiceRegister]
|
|
|
|
|
public class RestService
|
|
|
|
|
{
|
2025-07-03 12:17:15 +03:00
|
|
|
private readonly HttpClient _client;
|
2025-05-05 20:43:28 +03:00
|
|
|
private readonly ILogger _logger;
|
2024-12-22 16:38:47 +03:00
|
|
|
|
|
|
|
|
private readonly JsonSerializerOptions _serializerOptions = new()
|
|
|
|
|
{
|
|
|
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
|
|
|
WriteIndented = true
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-03 12:17:15 +03:00
|
|
|
public RestService(DebugService debug, HttpClient? client = null)
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2025-07-03 12:17:15 +03:00
|
|
|
_client = client ?? new HttpClient();
|
2025-05-05 20:43:28 +03:00
|
|
|
_logger = debug.GetLogger(this);
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
|
2025-06-22 10:40:42 +03:00
|
|
|
[Pure]
|
2025-02-01 18:19:18 +03:00
|
|
|
public async Task<T> GetAsync<T>(Uri uri, CancellationToken cancellationToken) where T : notnull
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2025-01-08 18:00:06 +03:00
|
|
|
var response = await _client.GetAsync(uri, cancellationToken);
|
2025-05-03 18:20:16 +03:00
|
|
|
return await ReadResult<T>(response, cancellationToken, uri);
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
|
2025-06-22 10:40:42 +03:00
|
|
|
[Pure]
|
2025-02-01 18:19:18 +03:00
|
|
|
public async Task<T> GetAsyncDefault<T>(Uri uri, T defaultValue, CancellationToken cancellationToken) where T : notnull
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2025-02-01 18:19:18 +03:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
return await GetAsync<T>(uri, cancellationToken);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
2025-05-05 20:43:28 +03:00
|
|
|
_logger.Error(e);
|
2025-02-01 18:19:18 +03:00
|
|
|
return defaultValue;
|
|
|
|
|
}
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
|
2025-06-22 10:40:42 +03:00
|
|
|
[Pure]
|
2025-02-01 18:19:18 +03:00
|
|
|
public async Task<K> PostAsync<K, T>(T information, Uri uri, CancellationToken cancellationToken) where K : notnull
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2025-01-08 18:00:06 +03:00
|
|
|
var json = JsonSerializer.Serialize(information, _serializerOptions);
|
|
|
|
|
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
|
|
|
|
var response = await _client.PostAsync(uri, content, cancellationToken);
|
2025-05-03 18:20:16 +03:00
|
|
|
return await ReadResult<K>(response, cancellationToken, uri);
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
|
2025-06-22 10:40:42 +03:00
|
|
|
[Pure]
|
2025-02-01 18:19:18 +03:00
|
|
|
public async Task<T> PostAsync<T>(Stream stream, Uri uri, CancellationToken cancellationToken) where T : notnull
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2025-01-08 18:00:06 +03:00
|
|
|
using var multipartFormContent =
|
|
|
|
|
new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture));
|
|
|
|
|
multipartFormContent.Add(new StreamContent(stream), "formFile", "image.png");
|
|
|
|
|
var response = await _client.PostAsync(uri, multipartFormContent, cancellationToken);
|
2025-05-03 18:20:16 +03:00
|
|
|
return await ReadResult<T>(response, cancellationToken, uri);
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
|
2025-06-22 10:40:42 +03:00
|
|
|
[Pure]
|
2025-02-01 18:19:18 +03:00
|
|
|
public async Task<T> DeleteAsync<T>(Uri uri, CancellationToken cancellationToken) where T : notnull
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2025-01-08 18:00:06 +03:00
|
|
|
var response = await _client.DeleteAsync(uri, cancellationToken);
|
2025-05-03 18:20:16 +03:00
|
|
|
return await ReadResult<T>(response, cancellationToken, uri);
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
|
2025-06-22 10:40:42 +03:00
|
|
|
[Pure]
|
2025-05-03 18:20:16 +03:00
|
|
|
private async Task<T> ReadResult<T>(HttpResponseMessage response, CancellationToken cancellationToken, Uri uri) where T : notnull
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
|
|
|
|
var content = await response.Content.ReadAsStringAsync(cancellationToken);
|
2025-01-30 20:18:40 +03:00
|
|
|
|
2025-02-01 18:19:18 +03:00
|
|
|
if (typeof(T) == typeof(string) && content is T t)
|
|
|
|
|
return t;
|
|
|
|
|
|
2024-12-22 16:38:47 +03:00
|
|
|
if (response.IsSuccessStatusCode)
|
|
|
|
|
{
|
2025-02-01 18:19:18 +03:00
|
|
|
return await response.Content.AsJson<T>();
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
2025-01-30 20:18:40 +03:00
|
|
|
|
2025-05-03 18:20:16 +03:00
|
|
|
throw new RestRequestException(response.Content, response.StatusCode, $"Error while processing {uri.ToString()}: {response.ReasonPhrase}");
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-03 18:20:16 +03:00
|
|
|
public sealed class RestRequestException(HttpContent content, HttpStatusCode statusCode, string message) : Exception(message)
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2025-02-01 18:19:18 +03:00
|
|
|
public HttpStatusCode StatusCode { get; } = statusCode;
|
|
|
|
|
public HttpContent Content { get; } = content;
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|