You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
5.0 KiB
168 lines
5.0 KiB
using System.Net;
|
|
using System.Text;
|
|
using System.Text.Json.Nodes;
|
|
using Connected.Interop;
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
namespace Connected.Net;
|
|
|
|
public static class HttpExtensions
|
|
{
|
|
private const string RequestArgumentsKey = "TP-REQUEST-ARGUMENTS";
|
|
|
|
public static async Task<JsonNode?> Deserialize(this HttpRequest request)
|
|
{
|
|
if (await ReadText(request) is not string text || string.IsNullOrWhiteSpace(text))
|
|
return default;
|
|
|
|
if (JsonNode.Parse(text, new JsonNodeOptions { PropertyNameCaseInsensitive = true }) is not JsonNode node)
|
|
return default;
|
|
|
|
request.HttpContext.SetRequestArguments(node);
|
|
|
|
return node;
|
|
}
|
|
public static async Task<T?> Deserialize<T>(this HttpRequest request)
|
|
{
|
|
if (await ReadText(request) is not string text || string.IsNullOrWhiteSpace(text))
|
|
return default;
|
|
|
|
return await Serializer.Deserialize<T>(text);
|
|
}
|
|
|
|
private static async Task<string> ReadText(HttpRequest request)
|
|
{
|
|
using var reader = new StreamReader(request.Body, Encoding.UTF8);
|
|
|
|
return await reader.ReadToEndAsync();
|
|
}
|
|
|
|
public static JsonNode? GetRequestArguments(this HttpContext context)
|
|
{
|
|
var result = context.Items[RequestArgumentsKey];
|
|
|
|
return result is null ? null : (JsonNode)result;
|
|
}
|
|
|
|
public static void SetRequestArguments(this HttpContext context, JsonNode arguments)
|
|
{
|
|
if (context is null)
|
|
return;
|
|
|
|
context.Items[RequestArgumentsKey] = arguments;
|
|
}
|
|
|
|
public static async Task<TResult?> Get<TResult>(this IHttpService factory, string? requestUri, CancellationToken cancellationToken = default)
|
|
{
|
|
return await HandleResponse<TResult>(await factory.CreateClient().SendAsync(CreateGetMessage(requestUri), cancellationToken));
|
|
}
|
|
|
|
public static async Task<TResult?> Get<TResult>(this IHttpService factory, string? requestUri, object content, CancellationToken cancellationToken = default)
|
|
{
|
|
return await HandleResponse<TResult>(await factory.CreateClient().SendAsync(await CreateGetMessage(requestUri, content), cancellationToken));
|
|
}
|
|
|
|
public static async Task Post(this IHttpService factory, string? requestUri, object? content, CancellationToken cancellationToken = default)
|
|
{
|
|
await HandleResponse(await factory.CreateClient().SendAsync(await CreatePostMessage(requestUri, content), cancellationToken));
|
|
}
|
|
public static async Task<TResult?> Post<TResult>(this IHttpService factory, string? requestUri, object? content, CancellationToken cancellationToken = default)
|
|
{
|
|
var client = factory.CreateClient();
|
|
var message = await CreatePostMessage(requestUri, content);
|
|
var response = await client.SendAsync(message, cancellationToken);
|
|
|
|
return await HandleResponse<TResult>(response);
|
|
}
|
|
private static HttpRequestMessage CreateGetMessage(string? requestUri)
|
|
{
|
|
return new HttpRequestMessage(HttpMethod.Get, requestUri);
|
|
}
|
|
|
|
private static async Task<HttpRequestMessage> CreateGetMessage(string? requestUri, object content)
|
|
{
|
|
return new HttpRequestMessage(HttpMethod.Get, requestUri)
|
|
{
|
|
Content = await CreateJsonContent(content)
|
|
};
|
|
}
|
|
|
|
private static async Task<HttpRequestMessage> CreatePostMessage(string? requestUri, object? content)
|
|
{
|
|
return new HttpRequestMessage(HttpMethod.Post, requestUri)
|
|
{
|
|
Content = await CreateJsonContent(content)
|
|
};
|
|
}
|
|
private static async Task HandleResponse(HttpResponseMessage response)
|
|
{
|
|
if (!response.IsSuccessStatusCode)
|
|
await HandleResponseException(response);
|
|
}
|
|
|
|
private static async Task<T?> HandleResponse<T>(HttpResponseMessage response)
|
|
{
|
|
if (!response.IsSuccessStatusCode)
|
|
await HandleResponseException(response);
|
|
|
|
var content = response.Content.ReadAsStringAsync().Result;
|
|
|
|
if (IsNull(content))
|
|
return default;
|
|
|
|
return await Serializer.Deserialize<T>(content);
|
|
}
|
|
|
|
private static async Task HandleResponseException(HttpResponseMessage response)
|
|
{
|
|
var ex = await ParseException(response.Content);
|
|
|
|
if (ex is null)
|
|
throw new WebException(response.ReasonPhrase);
|
|
|
|
var source = string.Empty;
|
|
var message = string.Empty;
|
|
|
|
if (ex["source"] is JsonNode sourceNode)
|
|
source = sourceNode.GetValue<string>();
|
|
|
|
if (ex["message"] is JsonNode messageNode)
|
|
message = messageNode.GetValue<string>();
|
|
|
|
throw new WebException(message) { Source = source };
|
|
}
|
|
|
|
private static async Task<JsonNode?> ParseException(HttpContent responseContent)
|
|
{
|
|
if (responseContent is null)
|
|
return default;
|
|
|
|
try
|
|
{
|
|
var rt = responseContent.ReadAsStringAsync().Result;
|
|
|
|
return await Serializer.Deserialize<JsonNode>(rt);
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
private static bool IsNull(string content)
|
|
{
|
|
return string.Equals(content, "null", StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(content);
|
|
}
|
|
|
|
private static async Task<HttpContent?> CreateJsonContent(object? content)
|
|
{
|
|
if (content is null || Convert.IsDBNull(content))
|
|
return new StringContent(string.Empty);
|
|
|
|
if (await Serializer.Serialize(content) is not string c)
|
|
return new StringContent(string.Empty, Encoding.UTF8, "application/json");
|
|
|
|
return new StringContent(c, Encoding.UTF8, "application/json");
|
|
}
|
|
|
|
}
|