Adding custom headers to Azure Functions response

Viewed 11524

I'm working on an Azure Function App (v2), which has a number of different functions inside the same Function App.

It is going to be deployed in multiple Azure regions, and I would like to add a custom header, that indicates which region served the request.

I know that I can let each function return HttpResponseMessage which can contain custom headers. Instead of duplicating that code to each function, I would like to make it centralized in the entire Function App project. Another drawback of returning HttpResponseMessage is that I would like to use IActionResult, so I can use JsonResult or OkObjectResult and similar return types.

With an ASP.NET MVC project, I could add a middleware which added the header or add the headers using web.config. Neither seems to be possible in a Function App.

How can this be done without having to return HttpResponseMessage and adding the header inside each function's Run method?

3 Answers

I was able to do this by accessing the HttpResponse object via the request's HttpContext.

For example:

req.HttpContext.Response.Headers.Add("ETag", entity.ETag);
return new OkObjectResult(entity);

produces: enter image description here

while researching the exact same problem, I came along this blog post. Basically, you derive a custom class fomr JsonResult, OKResult and so on and manipulate the ExecuteResult method and add your headers there.

public class ServiceUnavailableResult : StatusCodeResult {
    private readonly int _retryAfterHeaderValue;

    public ServiceUnavailableResult(int retryAfterHeaderValue) : base(500) {
        _retryAfterHeaderValue = retryAfterHeaderValue;
    }

    public override void ExecuteResult(ActionContext context) {
        base.ExecuteResult(context);
        
        context.HttpContext.Response.Headers.Add("Retry-After", _retryAfterHeaderValue.ToString());
    }
}

It does not fully help you, but if you only use like two or three classes when returning content, it might.

It is now possible to inject middleware that can add custom headers to functions responses.

Registration

public static void Main()
{
  var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(workerApplication =>
    {
      workerApplication.UseWhen<StampHttpHeaderMiddleware>((context) =>
      {
        // We want to use this middleware only for http trigger invocations.
        return context.FunctionDefinition.
          InputBindings.Values.First(
            a => a.Type.EndsWith("Trigger")).Type == "httpTrigger";
      });
    })
   .Build();
  host.Run();

Implementation

internal sealed class StampHttpHeaderMiddleware : IFunctionsWorkerMiddleware
{
    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
      context.GetHttpResponseData()?.Headers.Add("x-myCustomHeader", "custom header value");
    }
}

(code is adapted from the GitHub sample)

Related