Middleware support for Azure Functions v3.0
About this blog
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.
Middleware support in Azure Functions
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
- Out-of-process(Isolated)
- In-process
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
AzureFunctions.Extensions.Middleware
🛑 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.
Updates 3.0
- Separated concerns of Http and non-http triggers
- bug-fixes in accessing executionContext
- cleaner approach to access data for non-http triggers
Note: Breaking change of class name changes
- FunctionsMiddleware => HttpMiddleware
- TaskMiddleware => NonHttpMiddleware
- IMiddlewareBuilder => IHttpMiddlewareBuilder
- ServerlessMiddleware => HttpMiddlewareBase
Features
- Able to add multiple custom middlewares to the pipeline
- Able to access HTTP context inside the custom middleware
- Able to access ExecutionContext & data inside non-http triggers
- Able to inject middlewares in all the triggers available
- Able to bypass middlewares and return response
- Handle Crosscutting concerns of the application
- Logging
- Exception Handling
- CORS
- Performance Monitoring
- Caching
- Security
- OpenTelemetry
- Licenced under MIT - 100% free for personal and commercial use
Supported Frameworks
- NetCoreApp 3.1
- NET 5.0
- NET 6.0
Installation
Install with Package Manager Console
PM> Install-Package AzureFunctions.Extensions.Middleware
Usage
Getting Started
1. HTTP Triggers
1.1 Add HttpContextAccessor in Startup.cs
Inorder to access/modify HttpContext within custom middleware we need to inject HttpContextAccessor to DI in Startup.cs file
|
|
1.2. Add custom middlewares to the pipeline in Startup.cs
One or more custom middlewares can be added to the execution pipeline as below.
|
|
1.2.1 Use()
- Use() middleware takes custom middleware as parameter and will be applied to all the endpoints
1.2.2 UseWhen()
- 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.
1.3. Pass IHttpMiddlewareBuilder in Http trigger class
Pass IHttpMiddlewareBuilder dependency to the constructor of Http trigger class
|
|
1.4. Modify http triggers methods
All of our custom middlewares are added in the Startup.cs file and now we need to bind last middleware for our HttpTrigger method , use “_middlewareBuilder.ExecuteAsync(new HttpMiddleware(async (httpContext) =>{HTTP trigger code},executionContext)” to wrap the code.
NOTE: pass optional parameter {executionContext} to use it in the custom middlewares , refer 1.5 to see how to make use of executionContext
|
|
In the above example we have passed executionContext as parameter to HttpMiddleware. This will be made available to all the custom middleware that are registered in startup.cs
1.5 How to define Custom middlewares for http triggers?
All custom middleware of Http triggers should inherit from HttpMiddlewareBase and override InvokeAsync method . You will be able to access both HttpContext and ExecutionContext
Note You have access to execution context in all the custom middlewares , only if you pass the executionContext as 2nd parameter in the HttpMiddleware wrapper (refer 1.4) To access it use {this.ExecutionContext} , refer below
|
|
2. Non-HTTP Triggers
2.1 Add custom middlewares to the pipeline in Startup.cs
One or more custom middlewares can be added to the execution pipeline as below for non-http triggers
|
|
2.1.1 Use()
- Use() middleware takes custom middleware as parameter and will be applied to all the endpoints
NOTE: UseWhen is not available in non-http triggers
However you could use ExecutionContext in each custom middleware to perform similar logic :). Refer the examples given below
2.2. Pass INonHttpMiddlewareBuilder in Non-Http trigger class
Pass INonHttpMiddlewareBuilder dependency to the constructor of Non-Http trigger class
|
|
2.3. Modify non-http triggers methods
All of our custom middlewares are added in the Startup.cs file and now we need to bind last middleware for our HttpTrigger method , use “_middlewareBuilder.ExecuteAsync(new NonHttpMiddleware(async (httpContext) =>{HTTP trigger code},executionContext,data)” to wrap the code.
NOTE: pass optional parameters {executionContext,data} to use it in the custom middlewares , refer 1.5 to see how to make use of executionContext
|
|
In the above example we have passed both executionContext and timerinfo data as parameters to NonHttpMiddleware. This will be made available to all the custom middleware that are registered in startup.cs
2.4 How to define Custom middlewares for non-http triggers?
All custom middleware of Non-Http triggers should inherit from TaskMiddleware and override InvokeAsync method . You will be able to access both ExecutionContext and Data
Note You have access to execution context and data in all the custom middlewares , only if you pass the executionContext and data as 2nd,3rd parameter in the NonHttpMiddleware wrapper respectively (refer 1.4) To access it use {this.ExecutionContext}/{this.Data} , refer below
|
|
How to contribute?
If you wish to contribute to this open source or provide feedback, Feel free to reach out to me on below links
Github Source code
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
Special thanks
Join us
Please go ahead and join our discord channel (https://discord.gg/8Cs82yNS) to give some valuable feedbacks