Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpRequestData.Body cannot be read more than once. #2957

Open
rustichowie opened this issue Feb 6, 2025 · 6 comments
Open

HttpRequestData.Body cannot be read more than once. #2957

rustichowie opened this issue Feb 6, 2025 · 6 comments
Labels
area: http Items related to experience improvements for HTTP triggers Needs: Triage (Functions)

Comments

@rustichowie
Copy link

When using the .NET Core integration the HttpRequestData.Body property is unabled to be read more than once.
Since the stream has "CanSeek" set to false, we cannot reset its position before the HTTP Trigger picks up the request.

I'm unsure if this is intended or not, but it means that it is impossible to read the request body in a middleware, and also process the request in the function itself. This works as expected when not using the .NET Core integration.

There seems to be a different implementation of HttpRequestData, AspNetCoreHttpRequestData when using the .NET Core integration, and GrpcHttpRequestData when using the normal worker.

Repository to reproduce the issue: https://github.com/rustichowie/AzureFunction.StreamReadBug

Repro steps

  1. Create a new Azure Function using the default template
  2. Add a simple middleware that reads from the request body and reset the stream position back to zero.
  3. Add a HTTP Trigger that also tries to read from the same request body

Expected behavior

Expected behavior is for this to work without throwing an exception.

Actual behavior

Setting the position of the stream back to zero causes an NotSupportedException to be thrown.

@JAdluri JAdluri self-assigned this Feb 10, 2025
@jviau jviau transferred this issue from Azure/azure-functions-host Feb 10, 2025
@dhudy
Copy link

dhudy commented Feb 20, 2025

Experiencing the same issue here. Makes trying to do some custom auth work a bit annoying!

@Mivaweb
Copy link

Mivaweb commented Feb 21, 2025

Referencing existing closed issue: #1911

@dhudy
Copy link

dhudy commented Feb 21, 2025

Thanks for the reference for the temporary fix but that cannot be the real long term solution. This feels like a bug of some kind.

@Mivaweb
Copy link

Mivaweb commented Feb 21, 2025

I can confirm the same NotSupportedException exception when using the Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore nuget package.

If I remove this package and switch to using the ConfigureFunctionsWorkerDefaults method:

var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults(builder =>
{
    builder.UseMiddleware<CustomMiddleware>();
})
.Build();
await host.RunAsync();

And then using the following code in my middleware:

public class CustomMiddleware : IFunctionsWorkerMiddleware
{
    public async Task Invoke(
        FunctionContext context,
        FunctionExecutionDelegate next)
    {
        var logger = context.GetLogger("CustomMiddleware");
        logger.LogInformation("Greetings from the custom middleware");

        var requestData = await context.GetHttpRequestDataAsync();

        if(requestData is not null)
        {
            var body = await requestData.ReadAsStringAsync();
            requestData.Body.Seek(0, SeekOrigin.Begin);
        }
        
        await next.Invoke(context);
    }
}

I can read the body and reset the stream without issues.

Then in my Function, I can successfully read the request again:

    [Function(nameof(HttpTriggerRun))]
    public async Task<HttpResponseData> HttpTriggerRun(
        [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req)
    {
        _logger.LogInformation("C# HTTP trigger function processed a request.");

        var request = await req.ReadAsStringAsync();

        var response = req.CreateResponse(System.Net.HttpStatusCode.OK);

        await response.WriteStringAsync("Result from HTTP trigger function.");

        return response;
    }

@rustichowie
Copy link
Author

The difference between using the .NET Core integration package or not in this case is the implementation of HttpRequestData. So the bug is with the AspNetCoreHttpRequestData implementation.

@dhudy
Copy link

dhudy commented Feb 21, 2025

https://github.com/Azure/azure-functions-dotnet-worker/blob/ee63bff74d848e4c12234a4099fbadc0152c90ec/extensions/Worker.Extensions.Http.AspNetCore/src/HttpDataModel/AspNetCoreHttpRequestData.cs#L35C25-L35C32

Looks like the implementation utilizes the base abstract Stream and when executing it is of type https://github.com/dotnet/aspnetcore/blob/main/src/Servers/Kestrel/Core/src/Internal/Http/HttpRequestStream.cs which does not have those methods implemented.

@satvu satvu added the area: http Items related to experience improvements for HTTP triggers label Mar 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: http Items related to experience improvements for HTTP triggers Needs: Triage (Functions)
Projects
None yet
Development

No branches or pull requests

5 participants