Middleware support for Azure Functions

Hey folks!, In this blog we will see about a library AzureFunctions.Extensions.Middleware that I developed to make use of middleware pattern to address some of the cross-cutting concerns of our applications.


Historically we always have known .NET Azure Functions have been in the in-process mode. Until the release of .NET 5, now there are two modes in which we can run Azure Functions

In the out-of-process mode we have native support for middleware as per the design ( we have direct control over the execution of our function app, which runs as a separate process). But in the In-Process mode there is no middleware capability as we don’t have full control over the application’s startup and dependencies it consumes.

Find more details here

https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i63738y3eut7v8tx9hka.png


🛑 It is now obvious that we won't be having a direct way to access the pipeline of execution in the traditional In-Process mode which most of us are using in the production environments.

AzureFunctions.Extensions.Middleware is supported by below frameworks

  • NetCoreapp 3.1
  • Net 5.0
  • Net 6.0
1
Install-Package AzureFunctions.Extensions.Middleware

Inorder to access/modify HttpContext within custom middleware we need to add HttpContextAccessor in Startup.cs file.

1
2
3

builder.Services.AddHttpContextAccessor();

One or more custom middlewares can be added to the execution pipeline using MiddlewareBuilder.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

builder.Services.AddTransient<IMiddlewareBuilder, MiddlewareBuilder>((serviceProvider) =>
            {
                var funcBuilder = new MiddlewareBuilder(serviceProvider.GetRequiredService<IHttpContextAccessor>());
                funcBuilder.Use(new ExceptionHandlingMiddleware(new LoggerFactory().CreateLogger(nameof(ExceptionHandlingMiddleware))));
                funcBuilder.UseWhen(ctx => ctx.Request.Path.StartsWithSegments("/api/Authorize"),
                    new AuthorizationMiddleware(new LoggerFactory().CreateLogger(nameof(AuthorizationMiddleware))));
                return funcBuilder;
            });

  • Use() middleware takes custom middleware as parameter and will be applied to all the endpoints
  • UseWhen() takes Func<HttpContext, bool> and custom middleware as parameters. If the condition is satisfied then middleware will be added to the pipeline of exectuion.

We can now add IMiddlewareBuilder as a dependency to our HTTP trigger function class.

1
2
3
4
5
6
7
8
9

        private readonly ILogger<Function1> _logger;
        private readonly IMiddlewareBuilder _middlewareBuilder;

        public Function1(ILogger<Function1> log, IMiddlewareBuilder middlewareBuilder)
        {
            _logger = log;            
            _middlewareBuilder = middlewareBuilder;
        }

Now we need to bind last middleware for our HttpTrigger method , to do that wrap our existing code inside Functionsmiddleware block “_middlewareBuilder.Execute(new FunctionsMiddleware(async (httpContext) =>{HTTP trigger code})”

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
 
return await _middlewareBuilder.ExecuteAsync(new FunctionsMiddleware(async (httpContext) =>
            {
                _logger.LogInformation("C# HTTP trigger function processed a request.");

                string name = httpContext.Request.Query["name"];                

                string requestBody = await new StreamReader(httpContext.Request.Body).ReadToEndAsync();
                dynamic data = JsonConvert.DeserializeObject(requestBody);
                name = name ?? data?.name;

                string responseMessage = string.IsNullOrEmpty(name)
                    ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                    : $"Hello, {name}. This HTTP triggered function executed successfully.";

                return new OkObjectResult(responseMessage);
            }));

If you wish to contribute to this open source or provide feedback, Feel free to reach out to me on below links


Leave a ⭐ in the below github repo if this library helped you at handling cross-cutting concerns of the application.

https://github.com/Cloud-Jas/AzureFunctions.Extensions.Middleware



Please go ahead and join our discord channel (https://discord.gg/8Cs82yNS) to give some valuable feedbacks