Skip to content

Commit

Permalink
Update FromBody converter to utilize DeserializeAsync (#2901)
Browse files Browse the repository at this point in the history
  • Loading branch information
liliankasem authored Jan 8, 2025
1 parent 2bbc2b9 commit 095fd09
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 37 deletions.
2 changes: 1 addition & 1 deletion extensions/Worker.Extensions.Http/release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@

### Microsoft.Azure.Functions.Worker.Extensions.Http <version>

- <entry>
- The 'FromBody' converter now utilizes `DeserializeAsync` for deserializing JSON content from the request body, enhancing support for asynchronous deserialization. (#2901)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Threading;
Expand Down Expand Up @@ -46,44 +47,23 @@ internal class DefaultFromBodyConversionFeature : IFromBodyConversionFeature
return ConvertBodyAsync(requestData, context, targetType);
}

private static ValueTask<object?> ConvertBodyAsync(HttpRequestData requestData, FunctionContext context, Type targetType)
private static async ValueTask<object?> ConvertBodyAsync(HttpRequestData requestData, FunctionContext context, Type targetType) => targetType switch
{
object? result;

if (targetType == typeof(string))
{
result = requestData.ReadAsString();
}
else if (targetType == typeof(byte[]))
{
result = ReadBytes(requestData, context.CancellationToken);
}
else if (targetType == typeof(Memory<byte>))
{
Memory<byte> bytes = ReadBytes(requestData, context.CancellationToken);
result = bytes;
}
else if (HasJsonContentType(requestData))
{
ObjectSerializer serializer = requestData.FunctionContext.InstanceServices.GetService<IOptions<WorkerOptions>>()?.Value?.Serializer
?? throw new InvalidOperationException("A serializer is not configured for the worker.");

result = serializer.Deserialize(requestData.Body, targetType, context.CancellationToken);
}
else
{
throw new InvalidOperationException($"The type '{targetType}' is not supported by the '{nameof(DefaultFromBodyConversionFeature)}'.");
}

return new ValueTask<object?>(result);
}

private static byte[] ReadBytes(HttpRequestData requestData, CancellationToken cancellationToken)
_ when targetType == typeof(string) => await requestData.ReadAsStringAsync(),
_ when targetType == typeof(byte[]) => await ReadBytesAsync(requestData),
_ when targetType == typeof(Memory<byte>) => new Memory<byte>(await ReadBytesAsync(requestData)),
_ when HasJsonContentType(requestData) =>
await (requestData.FunctionContext.InstanceServices.GetService<IOptions<WorkerOptions>>()?.Value?.Serializer
?? throw new InvalidOperationException("A serializer is not configured for the worker."))
.DeserializeAsync(requestData.Body, targetType, context.CancellationToken),
_ => throw new InvalidOperationException($"The type '{targetType}' is not supported by the '{nameof(DefaultFromBodyConversionFeature)}'.")
};

private static async Task<byte[]> ReadBytesAsync(HttpRequestData requestData)
{
var bytes = new byte[requestData.Body.Length];
requestData.Body.Read(bytes, 0, bytes.Length);

return bytes;
using var memoryStream = new MemoryStream();
await requestData.Body.CopyToAsync(memoryStream);
return memoryStream.ToArray();
}

private static bool HasJsonContentType(HttpRequestData request)
Expand Down

0 comments on commit 095fd09

Please sign in to comment.