Useful APIs for writing azure functions middleware
One of the benefits of using isolated (out-of-process) model is the ability to plug in custom middlewares in the invocation pipeline. In this post, I will go through some of the handy APIs you can use to make your middleware authoring experience easier. All these APIs are extension methods on FunctionContext
instance which is available in the Invoke
method of the middleware.
HTTP Trigger specific APIs
Let us take a look at 2 APIs specific to Http triggers.
GetHttpRequestDataAsync
The GetHttpRequestDataAsync
extension method can be used to obtain an instance of HttpRequestData
when called during an http trigger invocation. In the isolated function model, the HttpRequestData instance represents the http trigger specific information, which is useful when you want to read/update http trigger specific data, such as request/response headers and cookies. The GetHttpRequestDataAsync
returns a ValueTask<HttpRequestData?>
instance, which you could await to get the HttpRequestData
instance.
HttpRequestData? httpReqData = await functionContext.GetHttpRequestDataAsync();
This method will return null
if called during a non http trigger invocation.
GetHttpResponseData
The GetHttpResponseData
extension method can be used to get an instance of HttpResponseData
when called during an http trigger invocation. This method will return null
if called during a non http trigger invocation or when the function return type is not HttpResponseData
.
The following is an example of a middleware implementation which reads the HttpRequestData instance and updates the HttpResponseData instance during function execution. This middleware checks for the presence of a specific request header(x-correlationId
), and when present uses the header value to stamp a response header. Otherwise, it generates a new GUID value and uses that for stamping the response header.
We can use the UseWhen
extension method to register this middleware, where we can write a predicate which returns true, only when the invocation is for an http trigger. This way, our middleware will be participating in the invocation pipeline only for http trigger invocations.
APIs applicable to all trigger types.
GetInvocationResult
The GetInvocationResult
method gets an instance of InvocationResult
, which represents the result of the current function execution. The InvocationResult
type has a Value
property to get or set the value as needed.
This method is useful when you want to alter the return value of the function inside a middleware. For example, you can write a global exception handler like below where you will update the return value when an exception happens during the invocation.
There is another overload of GetInvocationResult
where you can specify the type you are expecting as the return type of the invocation.
var invocationResult = context.GetInvocationResult<HttpResponseData>();
GetOutputBindings
The GetOutputBindings
method gets the output binding entries collection for the current function execution. Each entry in the collection is of type OutputBindingData<T>
. You can use the Value
property to get or set the value as needed.
IEnumerable<OutputBindingData<object>>? allOutputBindings = context.GetOutputBindings<object>();
This method is useful if you want to update the invocation result of a function which has multiple output bindings.
For example, if you have a function like below where the return type of the function is a type which has properties decorated with output binding attributes.
You can use the GetOutputBindings
method to get the output binding entries and update them as needed. Below is an example where we are updating the value of the queue output binding entry.
BindInputAsync
The BindInputAsync
method binds an input binding item for the requested BindingMetadata instance. For example, you can use this method when you have a function with a BlobInput
input binding that needs to be accessed or updated by your middleware. Imagine you have a function like below,
You can access all the input bindings for your function from the function context(via the FunctionDefinition
property) and update the entry values. In the below snippet, I am updating only the blob input entry’s value.
Please give these APIs a try. These are available from version 1.8.0-preview1 onwards.
Cheers