RasmusW
RasmusW

Reputation: 3461

Adding custom headers to Azure Functions response

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?

Upvotes: 24

Views: 20410

Answers (3)

RasmusW
RasmusW

Reputation: 3461

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");
      await next(context);
    }
}

(code is adapted from the GitHub sample)

Upvotes: 2

Claas Diederichs
Claas Diederichs

Reputation: 156

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 ExecuteResultAsync method and add your headers there.

public class ServiceUnavailableResult : StatusCodeResult {
    private readonly int _retryAfterHeaderValue;

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

    public override async Task ExecuteResultAsync(ActionContext context) {
        await base.ExecuteResultAsync(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.

Upvotes: 3

bvpb
bvpb

Reputation: 1476

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

Upvotes: 45

Related Questions