using System.Net.Http.Headers;
using System.Text.Json.Serialization;
using Elsa.Extensions;
using Elsa.Http.ContentWriters;
using Elsa.Workflows.Core;
using Elsa.Workflows.Core.Attributes;
using Elsa.Workflows.Core.Contracts;
using Elsa.Workflows.Core.Models;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Http;
using HttpRequestHeaders = Elsa.Http.Models.HttpRequestHeaders;
namespace Elsa.Http;
///
/// Send an HTTP request.
///
[Activity("Elsa", "HTTP", "Send an HTTP request.", DisplayName = "Flow HTTP Request", Kind = ActivityKind.Task)]
[PublicAPI]
public class FlowSendHttpRequest : SendHttpRequestBase
{
///
/// A list of expected status codes to handle.
///
[Input(Description = "A list of expected status codes to handle.", UIHint = InputUIHints.MultiText)]
public Input> ExpectedStatusCodes { get; set; } = default!;
///
protected override async ValueTask HandleResponseAsync(ActivityExecutionContext context, HttpResponseMessage response)
{
var expectedStatusCodes = ExpectedStatusCodes.GetOrDefault(context) ?? new List(0);
var statusCode = (int)response.StatusCode;
var hasMatchingStatusCode = expectedStatusCodes.Contains(statusCode);
var outcome = hasMatchingStatusCode ? statusCode.ToString() : "Unmatched status code";
await context.CompleteActivityWithOutcomesAsync(outcome);
}
}
///
/// Send an HTTP request.
///
[Activity("Elsa", "HTTP", "Send an HTTP request.", DisplayName = "HTTP Request", Kind = ActivityKind.Task)]
[PublicAPI]
public class SendHttpRequest : SendHttpRequestBase
{
///
/// A list of expected status codes to handle and the corresponding activity to execute when the status code matches.
///
[Input(
Description = "A list of expected status codes to handle and the corresponding activity to execute when the status code matches.",
UIHint = "http-status-codes"
)]
public ICollection ExpectedStatusCodes { get; set; } = new List();
///
/// The activity to execute when the HTTP status code does not match any of the expected status codes.
///
[Port]
public IActivity? UnmatchedStatusCode { get; set; }
///
protected override async ValueTask HandleResponseAsync(ActivityExecutionContext context, HttpResponseMessage response)
{
var expectedStatusCodes = ExpectedStatusCodes;
var statusCode = (int)response.StatusCode;
var matchingCase = expectedStatusCodes.FirstOrDefault(x => x.StatusCode == statusCode);
var activity = matchingCase?.Activity ?? UnmatchedStatusCode;
await context.ScheduleActivityAsync(activity, OnChildActivityCompletedAsync);
}
private async ValueTask OnChildActivityCompletedAsync(ActivityExecutionContext context, ActivityExecutionContext childContext)
{
await context.CompleteActivityAsync();
}
}
///
/// A binding between an HTTP status code and an activity.
///
public class HttpStatusCodeCase
{
///
/// Creates a new instance of the class.
///
[JsonConstructor]
public HttpStatusCodeCase()
{
}
///
/// Creates a new instance of the class.
///
public HttpStatusCodeCase(int statusCode, IActivity activity)
{
StatusCode = statusCode;
Activity = activity;
}
///
/// The HTTP status code to match.
///
public int StatusCode { get; set; }
///
/// The activity to execute when the HTTP status code matches.
///
public IActivity? Activity { get; set; }
}
///
/// Base class for activities that send HTTP requests.
///
public abstract class SendHttpRequestBase : Activity
{
///
/// The URL to send the request to.
///
[Input]
public Input Url { get; set; } = default!;
///
/// The HTTP method to use when sending the request.
///
[Input(
Description = "The HTTP method to use when sending the request.",
Options = new[] { "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD" },
DefaultValue = "GET",
UIHint = InputUIHints.Dropdown
)]
public Input Method { get; set; } = new("GET");
///
/// The content to send with the request. Can be a string, an object, a byte array or a stream.
///
[Input(Description = "The content to send with the request. Can be a string, an object, a byte array or a stream.")]
public Input