Endpoint Mapping Based on Headers

Is it possible to map an endpoint definition to an implementation based on the presence or value of a header?

We have the same endpoint /x, which has a number of different implementations based on the presence, and then the value, of some header.

I was hoping Tapir would filter through the definitions until one matched, e.g:

endpoint.in("x").in(header("custom", "v1"))
endpoint.in("x").in(header("custom", "v2"))
// Default route, fallback

In some cases, this header is Authorization, i.e. providing a different route definition if a user is logged in or not.

Worst case I can implement just one endpoint, and extract the header as Optional[String], but for the purpose of documentation + clean code, it’s nice to have them separated.

This is possible in http4s by using pattern matching conditions, e.g req @ GET / Root / "x" if req.headers("custom").exists(...)

Yes and no.

By default, tapir follows OpenAPI’s approach, where an endpoint is uniquely defined by its path shape (incl. wildcards) + method. So there can be only one GET /x endpoint.

However, if you are not generating documentation for your endpoints, you might define multiple endpoints with the same path still. You will need to change the decode failure handler in the server interpreter’s options.

The task of the handler is to either provide a response (such as 400 Bad Request), when an endpoint fails to decode, or to return a “no match”, meaning that the next endpoint should be attempted. In the default failure handler, decode failures on headers cause a bad request response to be sent.

If you want a decode failure on an input to cause trying the next endpoint instead, use the onDecodeFailureNextEndpoint method (there’s an example in the docs)

That’s super useful, thank you @adamw ! Seems like keeping it in one endpoint is for the best at the moment then. Appreciate the time you took to write out the explanation :pray: