Updated HttpRequestTrigger activity to support reading request content body
This commit is contained in:
parent
cb8a66e116
commit
6731968803
11
Elsa.sln
11
Elsa.sln
|
|
@ -21,11 +21,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Abstractions", "src\co
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Persistence.Abstractions", "src\core\Elsa.Persistence.Abstractions\Elsa.Persistence.Abstractions.csproj", "{A5829896-89C5-4C4E-ADC7-C806C8077316}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esla.Persistence.InMemory", "src\core\Esla.Persistence.InMemory\Esla.Persistence.InMemory.csproj", "{E93A1A6B-708F-4DCC-A399-1B8EC7682F92}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Runtime", "src\core\Elsa.Runtime\Elsa.Runtime.csproj", "{3C1DCAA2-D77E-4F96-9899-DA8E0E0C757F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esla.Runtime", "src\core\Esla.Runtime\Esla.Runtime.csproj", "{3C1DCAA2-D77E-4F96-9899-DA8E0E0C757F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esla.Runtime.Abstractions", "src\core\Esla.Runtime.Abstractions\Esla.Runtime.Abstractions.csproj", "{792362BF-D26D-46E9-8970-E5668941AA75}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Runtime.Abstractions", "src\core\Elsa.Runtime.Abstractions\Elsa.Runtime.Abstractions.csproj", "{792362BF-D26D-46E9-8970-E5668941AA75}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{35F44BE9-13D0-417C-A01A-F0787BEE6DC3}"
|
||||
EndProject
|
||||
|
|
@ -81,10 +79,6 @@ Global
|
|||
{A5829896-89C5-4C4E-ADC7-C806C8077316}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A5829896-89C5-4C4E-ADC7-C806C8077316}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A5829896-89C5-4C4E-ADC7-C806C8077316}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E93A1A6B-708F-4DCC-A399-1B8EC7682F92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E93A1A6B-708F-4DCC-A399-1B8EC7682F92}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E93A1A6B-708F-4DCC-A399-1B8EC7682F92}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E93A1A6B-708F-4DCC-A399-1B8EC7682F92}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3C1DCAA2-D77E-4F96-9899-DA8E0E0C757F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3C1DCAA2-D77E-4F96-9899-DA8E0E0C757F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3C1DCAA2-D77E-4F96-9899-DA8E0E0C757F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
|
@ -157,7 +151,6 @@ Global
|
|||
{300EE2D5-54C5-46F2-AD03-BB43589EA074} = {35F44BE9-13D0-417C-A01A-F0787BEE6DC3}
|
||||
{3130C574-557C-4DA2-933E-AED7A9EBE48A} = {35F44BE9-13D0-417C-A01A-F0787BEE6DC3}
|
||||
{A5829896-89C5-4C4E-ADC7-C806C8077316} = {35F44BE9-13D0-417C-A01A-F0787BEE6DC3}
|
||||
{E93A1A6B-708F-4DCC-A399-1B8EC7682F92} = {35F44BE9-13D0-417C-A01A-F0787BEE6DC3}
|
||||
{3C1DCAA2-D77E-4F96-9899-DA8E0E0C757F} = {35F44BE9-13D0-417C-A01A-F0787BEE6DC3}
|
||||
{792362BF-D26D-46E9-8970-E5668941AA75} = {35F44BE9-13D0-417C-A01A-F0787BEE6DC3}
|
||||
{35F44BE9-13D0-417C-A01A-F0787BEE6DC3} = {DA71CDAA-8DD3-4D5F-9FBD-8E4B37A2D925}
|
||||
|
|
|
|||
|
|
@ -14,5 +14,11 @@ namespace Elsa.Activities.Http.Activities
|
|||
/// The HTTP method that triggers this activity.
|
||||
/// </summary>
|
||||
public string Method { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A value indicating whether the HTTP request content body should be read and stored as part of the HTTP request model.
|
||||
/// The stored format depends on the content-type header.
|
||||
/// </summary>
|
||||
public bool ReadContent { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -13,16 +13,16 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\core\Elsa.Core\Elsa.Core.csproj"/>
|
||||
<ProjectReference Include="..\..\core\Elsa.Persistence.Abstractions\Elsa.Persistence.Abstractions.csproj"/>
|
||||
<ProjectReference Include="..\..\core\Esla.Runtime.Abstractions\Esla.Runtime.Abstractions.csproj"/>
|
||||
<ProjectReference Include="..\..\core\Elsa.Core\Elsa.Core.csproj" />
|
||||
<ProjectReference Include="..\..\core\Elsa.Persistence.Abstractions\Elsa.Persistence.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\..\core\Elsa.Runtime.Abstractions\Elsa.Runtime.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.AsyncInitialization" Version="1.1.1"/>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.0"/>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="2.2.0"/>
|
||||
<PackageReference Include="AspNetCore.AsyncInitialization" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Elsa.Activities.Http.Extensions
|
||||
{
|
||||
public static class HttpRequestExtensions
|
||||
{
|
||||
public static async Task<string> ReadBodyAsync(this HttpRequest request)
|
||||
{
|
||||
if (request.Body == null || request.Body == Stream.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
request.EnableBuffering();
|
||||
|
||||
using (var reader = new StreamReader(request.Body))
|
||||
{
|
||||
var content = await reader.ReadToEndAsync();
|
||||
request.Body.Seek(0, SeekOrigin.Begin);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,10 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Elsa.Activities.Http.Activities;
|
||||
using Elsa.Activities.Http.Extensions;
|
||||
using Elsa.Activities.Http.Models;
|
||||
using Elsa.Handlers;
|
||||
using Elsa.Models;
|
||||
using Elsa.Results;
|
||||
|
|
@ -29,14 +35,30 @@ namespace Elsa.Activities.Http.Handlers
|
|||
public override LocalizedString Description => T["Triggers when an incoming HTTP request is received."];
|
||||
protected override LocalizedString GetEndpoint() => T["Done"];
|
||||
|
||||
protected override ActivityExecutionResult OnExecute(HttpRequestTrigger activity, WorkflowExecutionContext workflowContext)
|
||||
protected override async Task<ActivityExecutionResult> OnExecuteAsync(HttpRequestTrigger activity, WorkflowExecutionContext workflowContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var request = httpContextAccessor.HttpContext.Request;
|
||||
var requestData = new
|
||||
var model = new HttpRequestModel
|
||||
{
|
||||
Path = request.Path
|
||||
Path = new Uri(request.Path.ToString(), UriKind.Relative),
|
||||
QueryString = request.Query.ToDictionary(x => x.Key, x => x.Value),
|
||||
Headers = request.Headers.ToDictionary(x => x.Key, x => x.Value),
|
||||
Method = request.Method
|
||||
};
|
||||
workflowContext.CurrentScope.LastResult = requestData;
|
||||
|
||||
if (activity.ReadContent)
|
||||
{
|
||||
if (request.HasFormContentType)
|
||||
{
|
||||
model.Form = (await request.ReadFormAsync(cancellationToken)).ToDictionary(x => x.Key, x => x.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
model.Content = await request.ReadBodyAsync();
|
||||
}
|
||||
}
|
||||
|
||||
workflowContext.CurrentScope.LastResult = model;
|
||||
return TriggerEndpoint("Done");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ namespace Elsa.Activities.Http.Middleware
|
|||
|
||||
public async Task InvokeAsync(HttpContext context, IWorkflowHost workflowHost, IHttpWorkflowCache httpWorkflowCache)
|
||||
{
|
||||
await workflowHost.TriggerWorkflowAsync("a", Variables.Empty, CancellationToken.None);
|
||||
var requestPath = new Uri(context.Request.Path.ToString(), UriKind.Relative);
|
||||
var cancellationToken = context.RequestAborted;
|
||||
var workflows = await httpWorkflowCache.GetWorkflowsByPathAsync(requestPath, cancellationToken).ToListAsync();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Elsa.Activities.Http.Models
|
||||
{
|
||||
public class HttpRequestHeaders : Dictionary<string, StringValues>
|
||||
{
|
||||
public string ContentType => this["content-type"];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Elsa.Activities.Http.Models
|
||||
{
|
||||
public class HttpRequestModel
|
||||
{
|
||||
public Uri Path { get; set; }
|
||||
public string Method { get; set; }
|
||||
public IDictionary<string, StringValues> QueryString { get; set; }
|
||||
public IDictionary<string, StringValues> Headers { get; set; }
|
||||
public string Content { get; set; }
|
||||
public IDictionary<string, StringValues> Form { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ namespace Elsa.Persistence.FileSystem.Extensions
|
|||
public static IServiceCollection AddWorkflowsFileSystemPersistence(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.TryAddSingleton<IFileSystem, System.IO.Abstractions.FileSystem>();
|
||||
services.AddSingleton<IWorkflowStore, FileSystemWorkflowStore>();
|
||||
services.AddScoped<IWorkflowStore, FileSystemWorkflowStore>();
|
||||
services.Configure<FileSystemStoreOptions>(configuration);
|
||||
|
||||
return services;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\Elsa.Core\Elsa.Core.csproj" />
|
||||
<ProjectReference Include="..\Elsa.Persistence.Abstractions\Elsa.Persistence.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\Esla.Runtime.Abstractions\Esla.Runtime.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\Elsa.Runtime.Abstractions\Elsa.Runtime.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,13 +1,14 @@
|
|||
using Elsa.Runtime;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.Runtime.Extensions
|
||||
namespace Esla.Runtime.Extensions
|
||||
{
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddWorkflowsHost(this IServiceCollection services)
|
||||
{
|
||||
return services
|
||||
.AddSingleton<IWorkflowHost, WorkflowHost>();
|
||||
.AddScoped<IWorkflowHost, WorkflowHost>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
<ProjectReference Include="..\..\activities\Elsa.Activities.Primitives\Elsa.Activities.Primitives.csproj" />
|
||||
<ProjectReference Include="..\..\core\Elsa.Core\Elsa.Core.csproj" />
|
||||
<ProjectReference Include="..\..\core\Elsa.Persistence.FileSystem\Elsa.Persistence.FileSystem.csproj" />
|
||||
<ProjectReference Include="..\..\core\Esla.Runtime\Esla.Runtime.csproj" />
|
||||
<ProjectReference Include="..\..\core\Elsa.Runtime\Elsa.Runtime.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using Elsa.Activities.Http.Extensions;
|
|||
using Elsa.Activities.Primitives.Extensions;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Persistence.FileSystem.Extensions;
|
||||
using Elsa.Runtime.Extensions;
|
||||
using Esla.Runtime.Extensions;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
},
|
||||
"AllowedHosts": "*",
|
||||
"FileStore": {
|
||||
"RootDirectory": "C:\\Activities\\Projects\\Elsa.Web.BootstrapTheme\\src\\web\\dashboard\\App_Data\\Sites\\Default\\workflows\\workflows",
|
||||
"RootDirectory": "C:\\Activities\\Projects\\Elsa\\src\\web\\dashboard\\Elsa.Web.Dashboard\\App_Data\\Sites\\Default\\elsa\\workflows",
|
||||
"Format": "YAML"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,14 @@ namespace Elsa.Web.Activities.Http.Drivers
|
|||
{
|
||||
model.Path = activity.Path;
|
||||
model.Method = activity.Method;
|
||||
model.ReadContent = activity.ReadContent;
|
||||
}
|
||||
|
||||
protected override void UpdateActivity(HttpRequestTriggerViewModel model, HttpRequestTrigger activity)
|
||||
{
|
||||
activity.Path = model.Path;
|
||||
activity.Method = model.Method;
|
||||
activity.ReadContent = model.ReadContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,8 @@ namespace Elsa.Web.Activities.Http.ViewModels
|
|||
[Required]
|
||||
public string Method { get; set; }
|
||||
|
||||
public bool ReadContent { get; set; }
|
||||
|
||||
public ICollection<SelectListItem> GetAvailableHttpMethods()
|
||||
{
|
||||
var availableHttpMethods = new[] { "GET", "POST", "PUT", "DELETE", "OPTIONS" };
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@
|
|||
<span asp-validation-for="Path" class="text-danger"></span>
|
||||
<small class="form-text text-muted">@T["The relative path that will trigger this activity. Example: '/webhooks/my'"]</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Method">@T["Method"]</label>
|
||||
<select class="form-control" asp-for="Method" asp-items="Model.GetAvailableHttpMethods()"></select>
|
||||
<span asp-validation-for="Method" class="text-danger"></span>
|
||||
<small class="form-text text-muted">@T["The HTTP method to match.'"]</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input"/>
|
||||
|
|
@ -19,8 +25,9 @@
|
|||
<small class="form-text text-muted">@T["Check to generate a nonce that needs to be included when invoking the URL.'"]</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Method">@T["Method"]</label>
|
||||
<select class="form-control" asp-for="Method" asp-items="Model.GetAvailableHttpMethods()"></select>
|
||||
<span asp-validation-for="Method" class="text-danger"></span>
|
||||
<small class="form-text text-muted">@T["The HTTP method to match.'"]</small>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input asp-for="ReadContent" type="checkbox" class="custom-control-input"/>
|
||||
<label asp-for="ReadContent" class="custom-control-label">@T["Read content"]</label>
|
||||
</div>
|
||||
<small class="form-text text-muted">@T["Check to read the request body. If the content type represents a form, the body is parsed as a collection of key/value pairs. Otherwise the body is stored as a raw string'"]</small>
|
||||
</div>
|
||||
Loading…
Reference in a new issue