Reputation: 3461
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
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
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
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);
Upvotes: 45