24

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?

2

3 Answers 3

45

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

Sign up to request clarification or add additional context in comments.

3 Comments

I tried sublcassing OkObjectResult but I can't set the header from in there. Was really hoping to make it cleaner. Any other ideas?
@BillNoel custom headers need to be set on the Response not the result. The result is only concerned with the return value, status code and content type (which I believe will affect the Content-Type header for the response), but to set a custom header you need to use the HttpResponse.
where I can find response headers in HttpRequestMessage object?
3

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.

1 Comment

This didn't quite work for us but overriding the ExecuteResultAsync method did.
2

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)

2 Comments

This is only for isolated right, not in-process function apps?
GetHttpResponseData() is null

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.