Thank you for the kind feedback!
There are probably several ways to accomplish your requirements in the Caddyfile… that was the first that came to my mind. You can read up on the handle directive to learn why that works.
In summary: there are different ways to structure or express routing logic. The traditional, “flat” Caddyfile way is to define behavior together (directives) and have routing be a secondary consideration (matchers). While this makes it easy to express many composable behaviors, it makes it difficult to express complex routing, with lots of “ifs” “ands” or “buts” so to speak. To visualize this, look at one of your later attempts. This is like a “flat” approach, where you just list the directives and matchers within them.
Another way is, I dunno what else to call it, so the “nested” approach. This is the inverse: routing is the primary consideration, and behavior is expressed within those routes. In this paradigm, routing logic is defined on the “outside” and behavior is defined on the “inside”. (In the “flat” paradigm, behavior is expressed on the “outside” and routing on the “inside”.) This is more like how nginx config works, with location
blocks. In the Caddyfile, the handle
and route
directives lend to this method, hence my solution.
Compare your initial config and my proposed solution and you’ll see the structural differences I’m talking about. I moved the routing logic to the “outside” and put the behavior on the “inside”.
The problem is that it’s difficult to express interdependent logic for whatever is on the “inside”. In other words, inside logic can’t be easily expressed if it depends on other inside logic. For example, in the “flat” paradigm, routing is on the inside: it is difficult to express routing logic that is dependent on other routing, like “if, else if, else if, else if, else”; conversely in the “nested” paradigm, it is difficult to express behavior that is dependent on other behaviors, like “do this, then this, then this, then this, and finally this”.
There are pros and cons to both approaches. Both are necessary, depending on what you need to do. In this case, your routing logic is more complex: you want to invoke certain handlers in a “if, else if, else if, else” fashion – so, the elegant solution is to put routing on the outside, hence the “nested” solution.
AFAIK, nginx config only does the “nested” paradigm, and Caddyfile v1 only did the “flat” paradigm. The v2 Caddyfile supports both! Just depends on what you need/want.
I hope that made any sense… I’d like to write up more about this later when it’s not midnight.