diff --git a/src/clients/Elsa.Api.Client/Contracts/IApiHttpRequestConfigurator.cs b/src/clients/Elsa.Api.Client/Contracts/IApiHttpRequestConfigurator.cs new file mode 100644 index 000000000..cdb295457 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Contracts/IApiHttpRequestConfigurator.cs @@ -0,0 +1,12 @@ +namespace Elsa.Api.Client.Contracts; + +/// +/// An interface for classes that can configure an HTTP request made to the API. +/// +public interface IApiHttpRequestConfigurator +{ + /// + /// Configures the HTTP request. + /// + Task ConfigureRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs b/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs index 182e1f315..525cbd5ca 100644 --- a/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs +++ b/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs @@ -2,6 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using Elsa.Api.Client.Contracts; using Elsa.Api.Client.Converters; +using Elsa.Api.Client.HttpMessageHandlers; using Elsa.Api.Client.Options; using Elsa.Api.Client.Resources.ActivityDescriptors.Contracts; using Elsa.Api.Client.Resources.ActivityExecutions.Contracts; @@ -29,11 +30,11 @@ public static class DependencyInjectionExtensions /// /// Adds the Elsa client to the service collection. /// - public static IServiceCollection AddElsaClient(this IServiceCollection services, Action configureOptions) + public static IServiceCollection AddElsaClient(this IServiceCollection services, Action? configureOptions = default) { - services.Configure(configureOptions); + services.Configure(configureOptions ?? (_ => { })); + services.AddScoped(); services.AddScoped(); - services.AddActivityTypeService(); services.AddApi(CreateRefitSettings); services.AddApi(CreateRefitSettings); @@ -46,14 +47,6 @@ public static class DependencyInjectionExtensions services.AddApi(CreateRefitSettings); return services; } - - /// - /// Adds activity type services to the service collection. - /// - public static IServiceCollection AddActivityTypeService(this IServiceCollection services) - { - return services; - } /// /// Adds a refit client for the specified API type. @@ -64,7 +57,16 @@ public static class DependencyInjectionExtensions public static void AddApi(this IServiceCollection services, Func settings) where T : class { services.AddRefitClient(settings) - .ConfigureHttpClient(ConfigureElsaApiHttpClient); + .ConfigureHttpClient(ConfigureElsaApiHttpClient) + .AddHttpMessageHandler(); + } + + /// + /// Creates an API client for the specified API type. + /// + public static T CreateApi(this IServiceProvider serviceProvider, Uri baseAddress) where T : class + { + return RestService.For(baseAddress.ToString(), CreateRefitSettings(serviceProvider)); } private static void ConfigureElsaApiHttpClient(IServiceProvider serviceProvider, HttpClient httpClient) @@ -73,7 +75,10 @@ public static class DependencyInjectionExtensions httpClient.BaseAddress = options.BaseAddress; options.ConfigureHttpClient?.Invoke(serviceProvider, httpClient); } - + + /// + /// Creates a instance configured for Elsa. + /// private static RefitSettings CreateRefitSettings(IServiceProvider serviceProvider) { JsonSerializerOptions serializerOptions = new() @@ -87,7 +92,7 @@ public static class DependencyInjectionExtensions var settings = new RefitSettings { - ContentSerializer = new SystemTextJsonContentSerializer(serializerOptions) + ContentSerializer = new SystemTextJsonContentSerializer(serializerOptions), }; return settings; diff --git a/src/clients/Elsa.Api.Client/HttpMessageHandlers/ApiHttpMessageHandler.cs b/src/clients/Elsa.Api.Client/HttpMessageHandlers/ApiHttpMessageHandler.cs new file mode 100644 index 000000000..a22a04f77 --- /dev/null +++ b/src/clients/Elsa.Api.Client/HttpMessageHandlers/ApiHttpMessageHandler.cs @@ -0,0 +1,28 @@ +using Elsa.Api.Client.Contracts; + +namespace Elsa.Api.Client.HttpMessageHandlers; + +/// +/// An HTTP message handler that invokes instances before sending the request. +/// +public class ApiHttpMessageHandler : DelegatingHandler +{ + private readonly IEnumerable _httpClientConfigurators; + + /// + public ApiHttpMessageHandler(IEnumerable httpClientConfigurators) + { + _httpClientConfigurators = httpClientConfigurators; + } + + /// + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + // Invoke configurators. + foreach (var httpClientConfigurator in _httpClientConfigurators) + await httpClientConfigurator.ConfigureRequestAsync(request, cancellationToken); + + // Continue processing the request + return await base.SendAsync(request, cancellationToken); + } +} \ No newline at end of file