Add support for single-value headers

This commit is contained in:
Sipke Schoorstra 2023-11-09 14:28:06 +01:00
parent 6552af5c59
commit 12b57a9abe
6 changed files with 101 additions and 33 deletions

View file

@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Elsa.Extensions;
using Elsa.Http.ActivityOptionProviders;
using Elsa.Http.ContentWriters;

View file

@ -1,9 +1,3 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Elsa.Http.Contracts;
using Elsa.Workflows.Core;
using Elsa.Workflows.Core.Models;
@ -20,7 +14,7 @@ internal static class HttpActivityExecutionContextExtensions
if (contentParser == null)
return null;
return await contentParser.ReadAsync(content, returnType, cancellationToken);
}
@ -28,19 +22,12 @@ internal static class HttpActivityExecutionContextExtensions
{
var value = context.Get(input.MemoryBlockReference());
if (value is IDictionary<string, string[]> dictionary1)
return dictionary1;
if (value is IDictionary<string, string> dictionary2)
return dictionary2.ToDictionary(x => x.Key, x => new[] { x.Value });
if (value is IDictionary<string, object> dictionary3)
return dictionary3.ToDictionary(
pair => pair.Key,
pair => pair.Value is ICollection<object> collection
? collection.Select(x => x.ToString()!).ToArray()
: new[] { pair.Value.ToString()! });
return Array.Empty<KeyValuePair<string, string[]>>();
return value switch
{
IDictionary<string, string[]> dictionary1 => dictionary1,
IDictionary<string, string> dictionary2 => dictionary2.ToDictionary(x => x.Key, x => new[] { x.Value }),
IDictionary<string, object> dictionary3 => dictionary3.ToDictionary(pair => pair.Key, pair => pair.Value is ICollection<object> collection ? collection.Select(x => x.ToString()!).ToArray() : new[] { pair.Value.ToString()! }),
_ => Array.Empty<KeyValuePair<string, string[]>>()
};
}
}

View file

@ -1,14 +1,17 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Elsa.Extensions;
using Elsa.Http.Serialization;
namespace Elsa.Http.Models;
/// <summary>
/// Represents the headers of an HTTP request.
/// </summary>
[JsonConverter(typeof(HttpRequestHeadersConverter))]
public class HttpRequestHeaders : Dictionary<string, string[]>
{
public string? ContentType => this.GetValue("content-type")?[0];
}
public class HttpResponseHeaders : Dictionary<string, string[]>
{
/// <summary>
/// Gets the content type of the request.
/// </summary>
public string? ContentType => this.GetValue("content-type")?[0];
}

View file

@ -0,0 +1,14 @@
using Elsa.Extensions;
namespace Elsa.Http.Models;
/// <summary>
/// Represents the headers of an HTTP response.
/// </summary>
public class HttpResponseHeaders : Dictionary<string, string[]>
{
/// <summary>
/// Gets the content type of the response.
/// </summary>
public string? ContentType => this.GetValue("content-type")?[0];
}

View file

@ -0,0 +1,70 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Elsa.Http.Models;
namespace Elsa.Http.Serialization;
/// <summary>
/// A custom JSON converter for <see cref="HttpRequestHeaders"/> that supports both single and multiple values.
/// </summary>
public class HttpRequestHeadersConverter : JsonConverter<HttpRequestHeaders>
{
/// <inheritdoc />
public override HttpRequestHeaders Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException("Expected StartObject token");
var headers = new HttpRequestHeaders();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
return headers;
if (reader.TokenType != JsonTokenType.PropertyName)
throw new JsonException("Expected a PropertyName token");
var key = reader.GetString()!;
reader.Read();
// If the next token is not a StartArray token, then we expect a String token.
switch (reader.TokenType)
{
case JsonTokenType.StartArray:
{
var values = new List<string>();
while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) values.Add(reader.GetString()!);
headers.Add(key, values.ToArray());
break;
}
case JsonTokenType.String:
{
var singleValue = reader.GetString()!;
headers.Add(key, new[] { singleValue });
break;
}
default:
throw new JsonException("Expected a String or StartArray token");
}
}
throw new JsonException("Expected an EndObject token");
}
/// <inheritdoc />
public override void Write(Utf8JsonWriter writer, HttpRequestHeaders value, JsonSerializerOptions options)
{
writer.WriteStartObject();
foreach (var header in value)
{
writer.WritePropertyName(header.Key);
writer.WriteStartArray();
foreach (var headerValue in header.Value) writer.WriteStringValue(headerValue);
writer.WriteEndArray();
}
writer.WriteEndObject();
}
}

View file

@ -1,4 +1,3 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using Elsa.Http.Models;