2022-10-25 13:52:55 +00:00
|
|
|
using System.Net.Http.Headers;
|
|
|
|
|
using Elsa.Http.ContentWriters;
|
|
|
|
|
using Elsa.Http.Models;
|
|
|
|
|
using Elsa.Http.Parsers;
|
|
|
|
|
using Elsa.Workflows.Core.Attributes;
|
|
|
|
|
using Elsa.Workflows.Core.Models;
|
|
|
|
|
using Elsa.Workflows.Management.Models;
|
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
|
using Microsoft.Extensions.Primitives;
|
|
|
|
|
using HttpRequestHeaders = Elsa.Http.Models.HttpRequestHeaders;
|
|
|
|
|
|
|
|
|
|
namespace Elsa.Http;
|
|
|
|
|
|
2022-11-23 10:20:00 +00:00
|
|
|
[Activity("Elsa", "HTTP", "Send Http Request.", DisplayName = "HTTP Request", Kind = ActivityKind.Task)]
|
2022-10-25 13:52:55 +00:00
|
|
|
public class SendHttpRequest : Activity
|
|
|
|
|
{
|
2022-10-27 10:05:30 +00:00
|
|
|
[Input] public Input<Uri?> Url { get; set; } = default!;
|
|
|
|
|
|
2022-10-25 13:52:55 +00:00
|
|
|
[Input(
|
2022-10-27 10:05:30 +00:00
|
|
|
Options = new[] { "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD" },
|
2022-10-25 13:52:55 +00:00
|
|
|
UIHint = InputUIHints.Dropdown
|
|
|
|
|
)]
|
|
|
|
|
public Input<string?> Method { get; set; }
|
2022-10-27 10:05:30 +00:00
|
|
|
|
2022-10-25 13:52:55 +00:00
|
|
|
public Input<string?> Content { get; set; } = default!;
|
2022-10-27 10:05:30 +00:00
|
|
|
|
2022-10-25 13:52:55 +00:00
|
|
|
[Input(
|
|
|
|
|
Options = new[] { "", "text/plain", "text/html", "application/json", "application/xml", "application/x-www-form-urlencoded" },
|
|
|
|
|
UIHint = InputUIHints.Dropdown
|
|
|
|
|
)]
|
|
|
|
|
public Input<string?> ContentType { get; set; } = default!;
|
2022-10-27 10:05:30 +00:00
|
|
|
|
|
|
|
|
[Input(Category = "Security")] public Input<string?> Authorization { get; set; } = default!;
|
2022-10-25 13:52:55 +00:00
|
|
|
|
|
|
|
|
public Input<bool> ReadContent { get; set; } = new(false);
|
2022-10-27 10:05:30 +00:00
|
|
|
|
2022-10-25 13:52:55 +00:00
|
|
|
[Input(
|
|
|
|
|
Options = new[] { "", "JsonElement", "Plain Text" },
|
|
|
|
|
UIHint = InputUIHints.Dropdown
|
|
|
|
|
)]
|
|
|
|
|
public Input<string?> ResponseContentParserName { get; set; } = default!;
|
2022-10-27 10:05:30 +00:00
|
|
|
|
|
|
|
|
[Input(Category = "Security")] public Input<Dictionary<string, string>?> RequestHeaders { get; set; } = new(new HttpRequestHeaders());
|
|
|
|
|
|
|
|
|
|
[Output] public Output<object>? ResponseContent { get; set; }
|
|
|
|
|
|
|
|
|
|
[Output] public Output<HttpResponseModel>? Response { get; set; }
|
2022-10-25 13:52:55 +00:00
|
|
|
|
|
|
|
|
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
|
|
|
|
|
{
|
|
|
|
|
var request = PrepareRequest(context);
|
2022-10-27 10:05:30 +00:00
|
|
|
|
|
|
|
|
var httpClientFactory = context.GetRequiredService<IHttpClientFactory>();
|
2022-10-25 13:52:55 +00:00
|
|
|
var httpClient = httpClientFactory.CreateClient(nameof(SendHttpRequest));
|
2022-10-27 10:05:30 +00:00
|
|
|
|
2022-10-25 13:52:55 +00:00
|
|
|
var cancellationToken = context.CancellationToken;
|
|
|
|
|
var response = await httpClient.SendAsync(request, cancellationToken);
|
2022-10-27 10:05:30 +00:00
|
|
|
|
|
|
|
|
var allHeaders =
|
2022-10-25 13:52:55 +00:00
|
|
|
response.Headers.ToDictionary(x => x.Key, x => x.Value.ToArray())
|
|
|
|
|
.Concat(response.Content.Headers.ToDictionary(x => x.Key, x => x.Value.ToArray()));
|
2022-10-27 10:05:30 +00:00
|
|
|
|
2022-10-25 13:52:55 +00:00
|
|
|
var responseModel = new HttpResponseModel(response.StatusCode, new Dictionary<string, string[]>())
|
|
|
|
|
{
|
|
|
|
|
StatusCode = response!.StatusCode,
|
|
|
|
|
Headers = new Dictionary<string, string[]>(allHeaders)
|
|
|
|
|
};
|
2022-10-27 10:05:30 +00:00
|
|
|
|
2022-10-25 13:52:55 +00:00
|
|
|
context.Set(Response, responseModel);
|
|
|
|
|
|
|
|
|
|
if (HasContent(response) && context.Get(ReadContent))
|
|
|
|
|
{
|
2022-10-27 10:05:30 +00:00
|
|
|
var parsers = context.GetServices<IHttpResponseContentReader>();
|
2022-10-25 13:52:55 +00:00
|
|
|
var formatter = SelectContentParser(parsers.ToList(), context.Get(ResponseContentParserName), context.Get(ContentType));
|
|
|
|
|
context.Set(ResponseContent, await formatter.ReadAsync(response, context, cancellationToken));
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-27 10:05:30 +00:00
|
|
|
|
2022-10-25 13:52:55 +00:00
|
|
|
private IHttpResponseContentReader SelectContentParser(List<IHttpResponseContentReader> parsers, string? parserName, string? contentType)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(parserName))
|
|
|
|
|
{
|
|
|
|
|
var simpleContentType = contentType?.Split(';').First() ?? "";
|
|
|
|
|
var parser = parsers.OrderByDescending(x => x.Priority).ToList();
|
|
|
|
|
|
|
|
|
|
return parser.FirstOrDefault(x => x.GetSupportsContentType(simpleContentType)) ?? parser.Last();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var parser = parsers.FirstOrDefault(x => x.Name == parserName);
|
|
|
|
|
|
|
|
|
|
if (parser == null)
|
|
|
|
|
throw new InvalidOperationException("The specified parser does not exist");
|
|
|
|
|
|
|
|
|
|
return parser;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-27 10:05:30 +00:00
|
|
|
|
|
|
|
|
private bool HasContent(HttpResponseMessage response) => response?.Content != null && response.Content.Headers.ContentLength > 0;
|
2022-10-25 13:52:55 +00:00
|
|
|
|
|
|
|
|
private HttpRequestMessage PrepareRequest(ActivityExecutionContext context)
|
|
|
|
|
{
|
2022-10-27 10:05:30 +00:00
|
|
|
var method = context.Get(Method)!;
|
|
|
|
|
var request = new HttpRequestMessage(new HttpMethod(method), context.Get(Url));
|
2022-10-25 13:52:55 +00:00
|
|
|
|
2022-10-27 10:05:30 +00:00
|
|
|
var headers = context.Get(RequestHeaders)!;
|
|
|
|
|
var requestHeaders = new HeaderDictionary(headers.ToDictionary(x => x.Key, x => new StringValues(x.Value.Split(','))));
|
2022-10-25 13:52:55 +00:00
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(context.Get(Authorization)))
|
|
|
|
|
request.Headers.Authorization = AuthenticationHeaderValue.Parse(context.Get(Authorization));
|
|
|
|
|
|
|
|
|
|
foreach (var header in requestHeaders)
|
|
|
|
|
request.Headers.Add(header.Key, header.Value.AsEnumerable());
|
|
|
|
|
|
2022-10-27 10:05:30 +00:00
|
|
|
var contentType = context.Get(ContentType)!;
|
|
|
|
|
var contentWriters = context.GetServices<IHttpRequestContentWriter>();
|
2022-10-25 13:52:55 +00:00
|
|
|
var contentWriter = SelectContentWriter(contentType, contentWriters);
|
|
|
|
|
request.Content = contentWriter.GetContent(contentType, context.Get(Content));
|
|
|
|
|
|
|
|
|
|
return request;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-27 10:05:30 +00:00
|
|
|
private IHttpRequestContentWriter SelectContentWriter(string contentType, IEnumerable<IHttpRequestContentWriter> requestContentWriters) =>
|
|
|
|
|
string.IsNullOrWhiteSpace(contentType) ? new StringHttpRequestContentWriter() : requestContentWriters.First(w => w.SupportsContentType(contentType));
|
|
|
|
|
}
|