< Summary

Information
Class: Elsa.Http.Features.HttpFeature
Assembly: Elsa.Http
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Http/Features/HttpFeature.cs
Line coverage
93%
Covered lines: 137
Uncovered lines: 10
Coverable lines: 147
Total lines: 260
Line coverage: 93.1%
Branch coverage
66%
Covered branches: 8
Total branches: 12
Branch coverage: 66.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Http/Features/HttpFeature.cs

#LineLine coverage
 1using Elsa.Expressions.Options;
 2using Elsa.Extensions;
 3using Elsa.Features.Abstractions;
 4using Elsa.Features.Attributes;
 5using Elsa.Features.Services;
 6using Elsa.Http.Bookmarks;
 7using Elsa.Http.ContentWriters;
 8using Elsa.Http.DownloadableContentHandlers;
 9using Elsa.Http.FileCaches;
 10using Elsa.Http.Handlers;
 11using Elsa.Http.Options;
 12using Elsa.Http.Parsers;
 13using Elsa.Http.PortResolvers;
 14using Elsa.Http.Resilience;
 15using Elsa.Http.Selectors;
 16using Elsa.Http.Services;
 17using Elsa.Http.Tasks;
 18using Elsa.Http.TriggerPayloadValidators;
 19using Elsa.Http.UIHints;
 20using Elsa.Resilience.Extensions;
 21using Elsa.Resilience.Features;
 22using Elsa.Workflows;
 23using FluentStorage;
 24using Microsoft.AspNetCore.Http;
 25using Microsoft.AspNetCore.StaticFiles;
 26using Microsoft.Extensions.DependencyInjection;
 27using Microsoft.Extensions.DependencyInjection.Extensions;
 28using Microsoft.Extensions.Options;
 29
 30namespace Elsa.Http.Features;
 31
 32/// <summary>
 33/// Installs services related to HTTP services and activities.
 34/// </summary>
 35[DependsOn(typeof(HttpJavaScriptFeature))]
 36[DependsOn(typeof(ResilienceFeature))]
 537public class HttpFeature(IModule module) : FeatureBase(module)
 38{
 32839    private Func<IServiceProvider, IHttpEndpointRoutesProvider> _httpEndpointRouteProvider = sp => sp.GetRequiredService
 112740    private Func<IServiceProvider, IHttpEndpointBasePathProvider> _httpEndpointBasePathProvider = sp => sp.GetRequiredSe
 41
 42    /// <summary>
 43    /// A delegate to configure <see cref="HttpActivityOptions"/>.
 44    /// </summary>
 645    public Action<HttpActivityOptions>? ConfigureHttpOptions { get; set; }
 46
 47    /// <summary>
 48    /// A delegate to configure <see cref="HttpFileCacheOptions"/>.
 49    /// </summary>
 550    public Action<HttpFileCacheOptions>? ConfigureHttpFileCacheOptions { get; set; }
 51
 52    /// <summary>
 53    /// A delegate that is invoked when authorizing an inbound HTTP request.
 54    /// </summary>
 22455    public Func<IServiceProvider, IHttpEndpointAuthorizationHandler> HttpEndpointAuthorizationHandler { get; set; } = sp
 56
 57    /// <summary>
 58    /// A delegate that is invoked when an HTTP workflow faults.
 59    /// </summary>
 1060    public Func<IServiceProvider, IHttpEndpointFaultHandler> HttpEndpointWorkflowFaultHandler { get; set; } = sp => sp.G
 61
 62    /// <summary>
 63    /// A delegate to configure the <see cref="IContentTypeProvider"/>.
 64    /// </summary>
 1065    public Func<IServiceProvider, IContentTypeProvider> ContentTypeProvider { get; set; } = _ => new FileExtensionConten
 66
 67    /// <summary>
 68    /// A delegate to configure the <see cref="IFileCacheStorageProvider"/>.
 69    /// </summary>
 1070    public Func<IServiceProvider, IFileCacheStorageProvider> FileCache { get; set; } = sp =>
 571    {
 072        var options = sp.GetRequiredService<IOptions<HttpFileCacheOptions>>().Value;
 073        var blobStorage = StorageFactory.Blobs.DirectoryFiles(options.LocalCacheDirectory);
 074        return new BlobFileCacheStorageProvider(blobStorage);
 575    };
 76
 77    /// <summary>
 78    /// A delegate to configure the <see cref="HttpClient"/> used when by the <see cref="FlowSendHttpRequest"/> and <see
 79    /// </summary>
 1180    public Action<IServiceProvider, HttpClient> HttpClient { get; set; } = (_, _) => { };
 81
 82    /// <summary>
 83    /// A delegate to configure the <see cref="HttpClientBuilder"/> for <see cref="HttpClient"/>.
 84    /// </summary>
 1585    public Action<IHttpClientBuilder> HttpClientBuilder { get; set; } = _ => { };
 86
 87    /// <summary>
 88    /// A list of <see cref="IHttpCorrelationIdSelector"/> types to register with the service collection.
 89    /// </summary>
 1090    public ICollection<Type> HttpCorrelationIdSelectorTypes { get; } = new List<Type>
 591    {
 592        typeof(HeaderHttpCorrelationIdSelector),
 593        typeof(QueryStringHttpCorrelationIdSelector)
 594    };
 95
 96    /// <summary>
 97    /// A list of <see cref="IHttpWorkflowInstanceIdSelector"/> types to register with the service collection.
 98    /// </summary>
 1099    public ICollection<Type> HttpWorkflowInstanceIdSelectorTypes { get; } = new List<Type>
 5100    {
 5101        typeof(HeaderHttpWorkflowInstanceIdSelector),
 5102        typeof(QueryStringHttpWorkflowInstanceIdSelector)
 5103    };
 104
 105    public HttpFeature WithHttpEndpointRoutesProvider<T>() where T : IHttpEndpointRoutesProvider
 106    {
 0107        return WithHttpEndpointRoutesProvider(sp => sp.GetRequiredService<T>());
 108    }
 109
 110    public HttpFeature WithHttpEndpointRoutesProvider(Func<IServiceProvider, IHttpEndpointRoutesProvider> httpEndpointRo
 111    {
 0112        _httpEndpointRouteProvider = httpEndpointRouteProvider;
 0113        return this;
 114    }
 115
 116    public HttpFeature WithHttpEndpointBasePathProvider<T>() where T : class, IHttpEndpointBasePathProvider
 117    {
 0118        Services.TryAddScoped<T>();
 0119        return WithHttpEndpointBasePathProvider(sp => sp.GetRequiredService<T>());
 120    }
 121
 122    public HttpFeature WithHttpEndpointBasePathProvider(Func<IServiceProvider, IHttpEndpointBasePathProvider> httpEndpoi
 123    {
 0124        _httpEndpointBasePathProvider = httpEndpointBasePathProvider;
 0125        return this;
 126    }
 127
 128    /// <inheritdoc />
 129    public override void Configure()
 130    {
 5131        Module.UseWorkflowManagement(management =>
 5132        {
 5133            management.AddVariableTypes([
 5134                typeof(HttpRouteData),
 5135                typeof(HttpRequest),
 5136                typeof(HttpResponse),
 5137                typeof(HttpResponseMessage),
 5138                typeof(HttpHeaders),
 5139                typeof(IFormFile),
 5140                typeof(HttpFile),
 5141                typeof(Downloadable)
 5142            ], "HTTP");
 5143
 5144            management.AddActivitiesFrom<HttpFeature>();
 10145        });
 146
 10147        Module.UseResilience(resilience => resilience.AddResilienceStrategyType<HttpResilienceStrategy>());
 5148    }
 149
 150    /// <inheritdoc />
 151    public override void Apply()
 152    {
 5153        var configureOptions = ConfigureHttpOptions ?? (options =>
 5154        {
 4155            options.BasePath = "/workflows";
 4156            options.BaseUrl = new Uri("http://localhost");
 9157        });
 158
 5159        var configureFileCacheOptions = ConfigureHttpFileCacheOptions ?? (options => { options.TimeToLive = TimeSpan.Fro
 160
 5161        Services.Configure(configureOptions);
 5162        Services.Configure(configureFileCacheOptions);
 163
 5164        var httpClientBuilder = Services.AddHttpClient<SendHttpRequestBase>(HttpClient);
 5165        HttpClientBuilder(httpClientBuilder);
 166
 5167        Services
 5168            .AddScoped<IRouteMatcher, RouteMatcher>()
 5169            .AddScoped<IRouteTable, RouteTable>()
 5170            .AddScoped<IAbsoluteUrlProvider, DefaultAbsoluteUrlProvider>()
 5171            .AddScoped<IRouteTableUpdater, DefaultRouteTableUpdater>()
 5172            .AddScoped<IHttpWorkflowLookupService, HttpWorkflowLookupService>()
 5173            .AddScoped(ContentTypeProvider)
 5174            .AddHttpContextAccessor()
 5175
 5176            // Handlers.
 5177            .AddNotificationHandler<UpdateRouteTable>()
 5178
 5179            // Content parsers.
 5180            .AddSingleton<IHttpContentParser, JsonHttpContentParser>()
 5181            .AddSingleton<IHttpContentParser, XmlHttpContentParser>()
 5182            .AddSingleton<IHttpContentParser, PlainTextHttpContentParser>()
 5183            .AddSingleton<IHttpContentParser, TextHtmlHttpContentParser>()
 5184            .AddSingleton<IHttpContentParser, FileHttpContentParser>()
 5185
 5186            // HTTP content factories.
 5187            .AddScoped<IHttpContentFactory, TextContentFactory>()
 5188            .AddScoped<IHttpContentFactory, JsonContentFactory>()
 5189            .AddScoped<IHttpContentFactory, XmlContentFactory>()
 5190            .AddScoped<IHttpContentFactory, FormUrlEncodedHttpContentFactory>()
 5191
 5192            // Activity property options providers.
 5193            .AddScoped<IPropertyUIHandler, HttpContentTypeOptionsProvider>()
 5194            .AddScoped<IPropertyUIHandler, HttpEndpointPathUIHandler>()
 5195            .AddScoped(_httpEndpointBasePathProvider)
 5196
 5197            // Port resolvers.
 5198            .AddScoped<IActivityResolver, SendHttpRequestActivityResolver>()
 5199
 5200            // HTTP endpoint handlers.
 5201            .AddScoped<AuthenticationBasedHttpEndpointAuthorizationHandler>()
 5202            .AddScoped<AllowAnonymousHttpEndpointAuthorizationHandler>()
 5203            .AddScoped<DefaultHttpEndpointFaultHandler>()
 5204            .AddScoped<DefaultHttpEndpointRoutesProvider>()
 5205            .AddScoped<DefaultHttpEndpointBasePathProvider>()
 5206            .AddScoped(HttpEndpointWorkflowFaultHandler)
 5207            .AddScoped(HttpEndpointAuthorizationHandler)
 5208            .AddScoped(_httpEndpointRouteProvider)
 5209
 5210            // Startup tasks.
 5211            .AddStartupTask<UpdateRouteTableStartupTask>()
 5212
 5213            // Downloadable content handlers.
 5214            .AddScoped<IDownloadableManager, DefaultDownloadableManager>()
 5215            .AddScoped<IDownloadableContentHandler, MultiDownloadableContentHandler>()
 5216            .AddScoped<IDownloadableContentHandler, BinaryDownloadableContentHandler>()
 5217            .AddScoped<IDownloadableContentHandler, StreamDownloadableContentHandler>()
 5218            .AddScoped<IDownloadableContentHandler, FormFileDownloadableContentHandler>()
 5219            .AddScoped<IDownloadableContentHandler, DownloadableDownloadableContentHandler>()
 5220            .AddScoped<IDownloadableContentHandler, UrlDownloadableContentHandler>()
 5221            .AddScoped<IDownloadableContentHandler, StringDownloadableContentHandler>()
 5222            .AddScoped<IDownloadableContentHandler, HttpFileDownloadableContentHandler>()
 5223
 5224            //Trigger payload validators.
 5225            .AddTriggerPayloadValidator<HttpEndpointTriggerPayloadValidator, HttpEndpointBookmarkPayload>()
 5226
 5227            // File caches.
 5228            .AddScoped(FileCache)
 5229            .AddScoped<ZipManager>()
 5230
 5231            // AuthenticationBasedHttpEndpointAuthorizationHandler requires Authorization services.
 5232            // We could consider creating a separate module for installing authorization services.
 5233            .AddAuthorization();
 234
 235        // HTTP clients.
 5236        Services.AddHttpClient<IFileDownloader, HttpClientFileDownloader>();
 237
 238        // Add selectors.
 30239        foreach (var httpCorrelationIdSelectorType in HttpCorrelationIdSelectorTypes)
 10240            Services.AddScoped(typeof(IHttpCorrelationIdSelector), httpCorrelationIdSelectorType);
 241
 30242        foreach (var httpWorkflowInstanceIdSelectorType in HttpWorkflowInstanceIdSelectorTypes)
 10243            Services.AddScoped(typeof(IHttpWorkflowInstanceIdSelector), httpWorkflowInstanceIdSelectorType);
 244
 5245        Services.Configure<ExpressionOptions>(options =>
 5246        {
 5247            options.AddTypeAlias<HttpRequest>("HttpRequest");
 5248            options.AddTypeAlias<HttpResponse>("HttpResponse");
 5249            options.AddTypeAlias<HttpResponseMessage>("HttpResponseMessage");
 5250            options.AddTypeAlias<HttpHeaders>("HttpHeaders");
 5251            options.AddTypeAlias<HttpRouteData>("RouteData");
 5252            options.AddTypeAlias<IFormFile>("FormFile");
 5253            options.AddTypeAlias<IFormFile[]>("FormFile[]");
 5254            options.AddTypeAlias<HttpFile>("HttpFile");
 5255            options.AddTypeAlias<HttpFile[]>("HttpFile[]");
 5256            options.AddTypeAlias<Downloadable>("Downloadable");
 5257            options.AddTypeAlias<Downloadable[]>("Downloadable[]");
 10258        });
 5259    }
 260}