< 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))]
 737public class HttpFeature(IModule module) : FeatureBase(module)
 38{
 41339    private Func<IServiceProvider, IHttpEndpointRoutesProvider> _httpEndpointRouteProvider = sp => sp.GetRequiredService
 501740    private Func<IServiceProvider, IHttpEndpointBasePathProvider> _httpEndpointBasePathProvider = sp => sp.GetRequiredSe
 41
 42    /// <summary>
 43    /// A delegate to configure <see cref="HttpActivityOptions"/>.
 44    /// </summary>
 1045    public Action<HttpActivityOptions>? ConfigureHttpOptions { get; set; }
 46
 47    /// <summary>
 48    /// A delegate to configure <see cref="HttpFileCacheOptions"/>.
 49    /// </summary>
 750    public Action<HttpFileCacheOptions>? ConfigureHttpFileCacheOptions { get; set; }
 51
 52    /// <summary>
 53    /// A delegate that is invoked when authorizing an inbound HTTP request.
 54    /// </summary>
 27955    public Func<IServiceProvider, IHttpEndpointAuthorizationHandler> HttpEndpointAuthorizationHandler { get; set; } = sp
 56
 57    /// <summary>
 58    /// A delegate that is invoked when an HTTP workflow faults.
 59    /// </summary>
 1460    public Func<IServiceProvider, IHttpEndpointFaultHandler> HttpEndpointWorkflowFaultHandler { get; set; } = sp => sp.G
 61
 62    /// <summary>
 63    /// A delegate to configure the <see cref="IContentTypeProvider"/>.
 64    /// </summary>
 1465    public Func<IServiceProvider, IContentTypeProvider> ContentTypeProvider { get; set; } = _ => new FileExtensionConten
 66
 67    /// <summary>
 68    /// A delegate to configure the <see cref="IFileCacheStorageProvider"/>.
 69    /// </summary>
 1470    public Func<IServiceProvider, IFileCacheStorageProvider> FileCache { get; set; } = sp =>
 771    {
 072        var options = sp.GetRequiredService<IOptions<HttpFileCacheOptions>>().Value;
 073        var blobStorage = StorageFactory.Blobs.DirectoryFiles(options.LocalCacheDirectory);
 074        return new BlobFileCacheStorageProvider(blobStorage);
 775    };
 76
 77    /// <summary>
 78    /// A delegate to configure the <see cref="HttpClient"/> used when by the <see cref="FlowSendHttpRequest"/> and <see
 79    /// </summary>
 1580    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>
 2185    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>
 1490    public ICollection<Type> HttpCorrelationIdSelectorTypes { get; } = new List<Type>
 791    {
 792        typeof(HeaderHttpCorrelationIdSelector),
 793        typeof(QueryStringHttpCorrelationIdSelector)
 794    };
 95
 96    /// <summary>
 97    /// A list of <see cref="IHttpWorkflowInstanceIdSelector"/> types to register with the service collection.
 98    /// </summary>
 1499    public ICollection<Type> HttpWorkflowInstanceIdSelectorTypes { get; } = new List<Type>
 7100    {
 7101        typeof(HeaderHttpWorkflowInstanceIdSelector),
 7102        typeof(QueryStringHttpWorkflowInstanceIdSelector)
 7103    };
 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    {
 7131        Module.UseWorkflowManagement(management =>
 7132        {
 7133            management.AddVariableTypes([
 7134                typeof(HttpRouteData),
 7135                typeof(HttpRequest),
 7136                typeof(HttpResponse),
 7137                typeof(HttpResponseMessage),
 7138                typeof(HttpHeaders),
 7139                typeof(IFormFile),
 7140                typeof(HttpFile),
 7141                typeof(Downloadable)
 7142            ], "HTTP");
 7143
 7144            management.AddActivitiesFrom<HttpFeature>();
 14145        });
 146
 14147        Module.UseResilience(resilience => resilience.AddResilienceStrategyType<HttpResilienceStrategy>());
 7148    }
 149
 150    /// <inheritdoc />
 151    public override void Apply()
 152    {
 7153        var configureOptions = ConfigureHttpOptions ?? (options =>
 7154        {
 4155            options.BasePath = "/workflows";
 4156            options.BaseUrl = new Uri("http://localhost");
 11157        });
 158
 7159        var configureFileCacheOptions = ConfigureHttpFileCacheOptions ?? (options => { options.TimeToLive = TimeSpan.Fro
 160
 7161        Services.Configure(configureOptions);
 7162        Services.Configure(configureFileCacheOptions);
 163
 7164        var httpClientBuilder = Services.AddHttpClient<SendHttpRequestBase>(HttpClient);
 7165        HttpClientBuilder(httpClientBuilder);
 166
 7167        Services
 7168            .AddScoped<IRouteMatcher, RouteMatcher>()
 7169            .AddScoped<IRouteTable, RouteTable>()
 7170            .AddScoped<IAbsoluteUrlProvider, DefaultAbsoluteUrlProvider>()
 7171            .AddScoped<IRouteTableUpdater, DefaultRouteTableUpdater>()
 7172            .AddScoped<IHttpWorkflowLookupService, HttpWorkflowLookupService>()
 7173            .AddScoped(ContentTypeProvider)
 7174            .AddHttpContextAccessor()
 7175
 7176            // Handlers.
 7177            .AddNotificationHandler<UpdateRouteTable>()
 7178
 7179            // Content parsers.
 7180            .AddSingleton<IHttpContentParser, JsonHttpContentParser>()
 7181            .AddSingleton<IHttpContentParser, XmlHttpContentParser>()
 7182            .AddSingleton<IHttpContentParser, PlainTextHttpContentParser>()
 7183            .AddSingleton<IHttpContentParser, TextHtmlHttpContentParser>()
 7184            .AddSingleton<IHttpContentParser, FileHttpContentParser>()
 7185
 7186            // HTTP content factories.
 7187            .AddScoped<IHttpContentFactory, TextContentFactory>()
 7188            .AddScoped<IHttpContentFactory, JsonContentFactory>()
 7189            .AddScoped<IHttpContentFactory, XmlContentFactory>()
 7190            .AddScoped<IHttpContentFactory, FormUrlEncodedHttpContentFactory>()
 7191
 7192            // Activity property options providers.
 7193            .AddScoped<IPropertyUIHandler, HttpContentTypeOptionsProvider>()
 7194            .AddScoped<IPropertyUIHandler, HttpEndpointPathUIHandler>()
 7195            .AddScoped(_httpEndpointBasePathProvider)
 7196
 7197            // Port resolvers.
 7198            .AddScoped<IActivityResolver, SendHttpRequestActivityResolver>()
 7199
 7200            // HTTP endpoint handlers.
 7201            .AddScoped<AuthenticationBasedHttpEndpointAuthorizationHandler>()
 7202            .AddScoped<AllowAnonymousHttpEndpointAuthorizationHandler>()
 7203            .AddScoped<DefaultHttpEndpointFaultHandler>()
 7204            .AddScoped<DefaultHttpEndpointRoutesProvider>()
 7205            .AddScoped<DefaultHttpEndpointBasePathProvider>()
 7206            .AddScoped(HttpEndpointWorkflowFaultHandler)
 7207            .AddScoped(HttpEndpointAuthorizationHandler)
 7208            .AddScoped(_httpEndpointRouteProvider)
 7209
 7210            // Startup tasks.
 7211            .AddStartupTask<UpdateRouteTableStartupTask>()
 7212
 7213            // Downloadable content handlers.
 7214            .AddScoped<IDownloadableManager, DefaultDownloadableManager>()
 7215            .AddScoped<IDownloadableContentHandler, MultiDownloadableContentHandler>()
 7216            .AddScoped<IDownloadableContentHandler, BinaryDownloadableContentHandler>()
 7217            .AddScoped<IDownloadableContentHandler, StreamDownloadableContentHandler>()
 7218            .AddScoped<IDownloadableContentHandler, FormFileDownloadableContentHandler>()
 7219            .AddScoped<IDownloadableContentHandler, DownloadableDownloadableContentHandler>()
 7220            .AddScoped<IDownloadableContentHandler, UrlDownloadableContentHandler>()
 7221            .AddScoped<IDownloadableContentHandler, StringDownloadableContentHandler>()
 7222            .AddScoped<IDownloadableContentHandler, HttpFileDownloadableContentHandler>()
 7223
 7224            //Trigger payload validators.
 7225            .AddTriggerPayloadValidator<HttpEndpointTriggerPayloadValidator, HttpEndpointBookmarkPayload>()
 7226
 7227            // File caches.
 7228            .AddScoped(FileCache)
 7229            .AddScoped<ZipManager>()
 7230
 7231            // AuthenticationBasedHttpEndpointAuthorizationHandler requires Authorization services.
 7232            // We could consider creating a separate module for installing authorization services.
 7233            .AddAuthorization();
 234
 235        // HTTP clients.
 7236        Services.AddHttpClient<IFileDownloader, HttpClientFileDownloader>();
 237
 238        // Add selectors.
 42239        foreach (var httpCorrelationIdSelectorType in HttpCorrelationIdSelectorTypes)
 14240            Services.AddScoped(typeof(IHttpCorrelationIdSelector), httpCorrelationIdSelectorType);
 241
 42242        foreach (var httpWorkflowInstanceIdSelectorType in HttpWorkflowInstanceIdSelectorTypes)
 14243            Services.AddScoped(typeof(IHttpWorkflowInstanceIdSelector), httpWorkflowInstanceIdSelectorType);
 244
 7245        Services.Configure<ExpressionOptions>(options =>
 7246        {
 7247            options.AddTypeAlias<HttpRequest>("HttpRequest");
 7248            options.AddTypeAlias<HttpResponse>("HttpResponse");
 7249            options.AddTypeAlias<HttpResponseMessage>("HttpResponseMessage");
 7250            options.AddTypeAlias<HttpHeaders>("HttpHeaders");
 7251            options.AddTypeAlias<HttpRouteData>("RouteData");
 7252            options.AddTypeAlias<IFormFile>("FormFile");
 7253            options.AddTypeAlias<IFormFile[]>("FormFile[]");
 7254            options.AddTypeAlias<HttpFile>("HttpFile");
 7255            options.AddTypeAlias<HttpFile[]>("HttpFile[]");
 7256            options.AddTypeAlias<Downloadable>("Downloadable");
 7257            options.AddTypeAlias<Downloadable[]>("Downloadable[]");
 14258        });
 7259    }
 260}