Azure / azure-functions-dotnet-worker

Azure Functions out-of-process .NET language worker
MIT License
407 stars 167 forks source link

.NET isolated ASP.NET Core integration: provide a way to define middleware before .UseAspNetCoreIntegration() #2280

Open gastonmuijtjens opened 5 months ago

gastonmuijtjens commented 5 months ago

Description

I am using isolated Azure Functions with ASP.NET Core integration (Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore). I want to be able to define my own middleware which runs after the default FunctionsHttpProxyingMiddleware (after await next(context);). However the extension method ConfigureFunctionsWebApplication on IHostBuilder does not provide a way to register middleware before the call to UseAspNetCoreIntegration() (which registers the FunctionsHttpProxyingMiddleware):

public static IHostBuilder ConfigureFunctionsWebApplication(this IHostBuilder builder, Action<HostBuilderContext, IFunctionsWorkerApplicationBuilder> configureWorker)
{
    builder.ConfigureFunctionsWorkerDefaults((hostBuilderContext, workerAppBuilder) =>
    {
        workerAppBuilder.UseAspNetCoreIntegration();
        configureWorker?.Invoke(hostBuilderContext, workerAppBuilder);
    });

    builder.ConfigureAspNetCoreIntegration();

    return builder;
}

If I would register my own custom middleware in Program.cs using the provided extension method on IHostBuilder, MyCustomMiddleware would run before FunctionsHttpProxyingMiddleware. This is not what I want, because the HttpContext attached to FunctionContext is not filled with the response, response code and response headers after the IActionResult was executed:

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication(worker =>
    {
        worker.UseMiddleware<MyCustomMiddleware>();
    })

Unfortunately I cannot implement my own implementation of the ConfigureFunctionsWebApplication extension method to solve this issue, because ConfigureAspNetCoreIntegration and some used classes are internal. Is there any way to register the middleware so that it would run before FunctionsHttpProxyingMiddleware?

satvu commented 4 months ago

@gastonmuijtjens Can you share more about the scenario you are trying to accomplish?

gastonmuijtjens commented 4 months ago

@gastonmuijtjens Can you share more about the scenario you are trying to accomplish?

Hi @satvu, thank you for your reply. In my specific scenario I want to be able to set the Content-Length header based on the length of the body. When not using the ASP.NET Core-integration, I am able to accomplish this by using the following middleware:

public class ContentLengthMiddleware : IFunctionsWorkerMiddleware
{
    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        await next(context);
        var httpResponseData = context.GetHttpResponseData();
        httpResponseData?.Headers.Add(HeaderNames.ContentLength, httpResponseData.Body.Length.ToString());
    }
}

However since I cannot run my own middleware after the middleware that handles the ASP.NET Core-integration, there is no way for me to retrieve the length of the response body.