2

Is there a standard way to enforce mandatory request headers in .Net Core Web APIs? I want all caller apps to pass some tracking headers so that I have some traceability for call volume.

I am aware that for Swagger, it can be done via OperationFilter and custom header attribute. But for direct calls, I can think of only using custom middleware to enforce this.

Is that the right way to do it or is there other standard way to enforce it or standard libraries available for this purpose?

Kit
  • 20,354
  • 4
  • 60
  • 103
askids
  • 1,406
  • 1
  • 15
  • 32

1 Answers1

1

Here are a few ways to do this. There's not really a "standard" way to do it, but these ways are very common.

Outside of your project

You can enforce required headers by customizing your reverse proxy. For example, Apigee allows you to customize its rules, including enforcing headers for certain URLs. This is great because it relieves pressure and implementation on your project's endpoints. The proxy should be configured to return a 400 BAD REQUEST in those cases.

Within your project, Middleware

Within the project's code, using ASP.NET middleware is one way to take care of this. You can create a middleware that checks for the existence of the headers, and then reject the request if they are missing.

Here is a simple example where the existence of MyHeader allows the next middleware to be called, but the lack of the header avoids invoking the next middleware.

public class HeaderChecker
{
    private readonly RequestDelegate _next;

    public HeaderChecker(RequestDelegate next) => _next = next;

    public async Task Invoke(HttpContext context)
    {
        if (!context.Request.Headers.ContainsKey("MyHeader"))
            context.Response.StatusCode = 400;
        else
            await _next.Invoke(context);
    }
}

with the registration that you would place in Startup.cs

builder.UseMiddleware<HeaderChecker>();

You could avoid the middleware, but then you end up bloating your controller's methods, which is usually frowned on. Either way this SO Q&A backs up the idea of returning the 400 from your code.

Within your project, using [FromHeader]

You can use the [FromHeader] attribute, which is probably the simplest approach that can work, though this does mean you'd have to bind the header to your model. If your intent is simply to ensure a header is present, and not related to your model in any way, then that might not be desirable.

As always, in development, it depends.

Kit
  • 20,354
  • 4
  • 60
  • 103
  • "You can create a middleware that checks for the existence of the headers, and then reject the request if they are missing." How? Can you point to an example please – Pat Long - Munkii Yebee Aug 18 '22 at 13:24
  • @PatLong-MunkiiYebee I've added an example. – Kit Aug 19 '22 at 00:16
  • @PatLong-MunkiiYebee Hm, I've used the other attributes, but never had the occasion to use `[FromHeader]`. I'll add to my answer in case someone stumbles over here. Thanks! – Kit Aug 22 '22 at 15:42
  • I have deleted my previous comment as what I said was wrong. I am not getting a 400 if the header is missing! – Pat Long - Munkii Yebee Oct 05 '22 at 10:19