Files
ReC/src/ReC.Application/RecActions/Commands/InvokeRecActionViewCommand.cs
TekH 0e7870b556 Refactor: remove HttpExtensions and inline HTTP method mapping
Removed HttpExtensions.cs and its extension methods for RestType-to-HttpMethod conversion. Introduced a private static CreateHttpRequestMessage method in InvokeRecActionViewCommandHandler to handle HTTP method mapping and request creation directly, reducing indirection and simplifying dependencies.
2026-03-02 14:31:38 +01:00

157 lines
6.5 KiB
C#

using MediatR;
using Microsoft.Extensions.Configuration;
using ReC.Application.Common;
using ReC.Application.Common.Constants;
using ReC.Application.Common.Dto;
using ReC.Application.Common.Exceptions;
using ReC.Application.Common.Procedures.InsertProcedure;
using ReC.Application.Results.Commands;
using ReC.Domain.Constants;
using System.Net;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
namespace ReC.Application.RecActions.Commands;
public record InvokeRecActionViewCommand : IRequest<bool>
{
public RecActionViewDto Action { get; set; } = null!;
}
public class InvokeRecActionViewCommandHandler(
ISender sender,
IHttpClientFactory clientFactory,
IConfiguration? config = null
) : IRequestHandler<InvokeRecActionViewCommand, bool>
{
public async Task<bool> Handle(InvokeRecActionViewCommand request, CancellationToken cancel)
{
var action = request.Action;
using var http = clientFactory.CreateClient(Http.ClientName);
if (action.RestType is not RestType restType)
throw new DataIntegrityException(
$"Rec action could not be invoked because the RestType value is null. " +
$"ProfileId: {action.ProfileId}, " +
$"Id: {action.Id}"
);
using var httpReq = CreateHttpRequestMessage(restType, action.EndpointUri);
if (action.Body is not null)
httpReq.Content = new StringContent(action.Body);
if (action.Headers is not null)
foreach (var header in action.Headers)
httpReq.Headers.Add(header.Key, header.Value);
switch (action.EndpointAuthType)
{
case EndpointAuthType.NoAuth:
break;
case EndpointAuthType.ApiKey:
if (action.EndpointAuthApiKey is string apiKey && action.EndpointAuthApiValue is string apiValue)
{
switch (action.EndpointAuthApiKeyAddTo)
{
case ApiKeyLocation.Header:
httpReq.Headers.Add(apiKey, apiValue);
break;
case ApiKeyLocation.Query:
var uriBuilder = new UriBuilder(httpReq.RequestUri!);
var query = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query);
query[apiKey] = apiValue;
uriBuilder.Query = query.ToString();
httpReq.RequestUri = uriBuilder.Uri;
break;
default:
throw new DataIntegrityException(
$"The API key location '{action.EndpointAuthApiKeyAddTo}' is not supported. " +
$"ProfileId: {action.ProfileId}, " +
$"Id: {action.Id}"
);
}
}
break;
case EndpointAuthType.BearerToken:
case EndpointAuthType.JwtBearer:
case EndpointAuthType.OAuth2:
if (action.EndpointAuthToken is string authToken)
httpReq.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
break;
case EndpointAuthType.BasicAuth:
if (action.EndpointAuthUsername is string authUsername && action.EndpointAuthPassword is string authPassword)
{
var basicAuth = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{authUsername}:{authPassword}"));
httpReq.Headers.Authorization = new AuthenticationHeaderValue("Basic", basicAuth);
}
break;
case EndpointAuthType.NtlmAuth:
if (!string.IsNullOrWhiteSpace(action.EndpointAuthUsername))
{
var credentials = new NetworkCredential(
action.EndpointAuthUsername,
action.EndpointAuthPassword,
action.EndpointAuthDomain);
var credentialCache = new CredentialCache { { httpReq.RequestUri!, "NTLM", credentials } };
httpReq.Options.Set(new HttpRequestOptionsKey<CredentialCache>("Credentials"), credentialCache);
}
break;
case EndpointAuthType.DigestAuth:
case EndpointAuthType.OAuth1:
case EndpointAuthType.AwsSignature:
// These authentication methods require more complex implementations,
// often involving multi-step handshakes or specialized libraries.
// They are left as placeholders for future implementation.
default:
throw new NotImplementedException(
$"The authentication type '{action.EndpointAuthType}' is not supported yet. " +
$"ProfileId: {action.ProfileId}, " +
$"Id: {action.Id}"
);
}
using var response = await http.SendAsync(httpReq, cancel);
var resBody = await response.Content.ReadAsStringAsync(cancel);
var resHeaders = response.Headers.ToDictionary();
var statusCode = (short)response.StatusCode;
await sender.ExecuteInsertProcedure(new InsertResultProcedure()
{
StatusId = statusCode,
ActionId = action.Id,
Header = JsonSerializer.Serialize(resHeaders, options: new() { WriteIndented = false }),
Body = resBody
}, config?["AddedWho"], cancel);
return response.IsSuccessStatusCode;
}
private static HttpRequestMessage CreateHttpRequestMessage(RestType restType, string? endpointUri)
{
var method = restType switch
{
RestType.Get => HttpMethod.Get,
RestType.Post => HttpMethod.Post,
RestType.Put => HttpMethod.Put,
RestType.Delete => HttpMethod.Delete,
RestType.Patch => HttpMethod.Patch,
RestType.Head => HttpMethod.Head,
RestType.Options => HttpMethod.Options,
RestType.Trace => HttpMethod.Trace,
RestType.Connect => HttpMethod.Connect,
RestType.None => throw new ArgumentOutOfRangeException(nameof(restType), $"The RestType value '{restType}' is not valid."),
_ => new HttpMethod(restType.ToString().ToUpperInvariant())
};
return new HttpRequestMessage(method, endpointUri);
}
}