Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2 proposal: New 'route' directive for Caddyfile #2911

mholt opened this issue Dec 2, 2019 · 1 comment

v2 proposal: New 'route' directive for Caddyfile #2911

mholt opened this issue Dec 2, 2019 · 1 comment


Copy link

@mholt mholt commented Dec 2, 2019

The v2 Caddyfile makes most simple sites easy to set up because the order of the directives does not matter, unlike with Caddy's native JSON. For example, in the Caddyfile, you can put a rewrite directive after a file_server directive and it is smart enough to do the rewrite first, then serve static files last. Obviously, the rewrite is useless if it doesn't occur until after the response has been written by the file server!

Similarly, you'd want compression to come after templates, so that templates doesn't operate on a compressed, binary stream.

The point is, the order matters, and the Caddyfile takes away the fuss of ordering by hard-coding the order for you. With the Caddyfile, it is much harder to write routes with logical errors due to handler order.

However, this is not ideal for all situations. Sometimes, you want a redirect before a rewrite for example, or you want one directive to immediately precede another so that they act as one unit.

The Caddyfile makes it difficult to gain extra control; currently, one has to drop down to JSON and craft their route manually.

However, it seems that a widespread need could be satisfied with a way to execute directives in the order they appear in some isolation (i.e. not a global change).

A new route directive block would execute the directives inside it more literally. Its directives would be evaluated in the order they appear and allow directives to be combined in a specific way the user desires.

All matching route blocks would be executed first, in the order of appearance in the Caddyfile, before other directives.

Matchers cannot be defined in routes.

Directives outside of routes keep to the hard-coded/pre-defined order. This helps reduce user error and is still easy enough for simple configs. This way, the order won't matter for most users. Routes are intended to be an advanced feature to give you more control without having to drop all the way down to JSON.


root * /var/www/site
encode gzip


route /api {
  strip_prefix  /api

reverse_proxy =/




matcher foo {
    header Foo foobar

route match:foo {
    rewrite /prepend{uri}
    proxy localhost:9000

Matching routes are always executed first, i.e. they take priority over directives outside a route block.

One major nuance is that rewrite, which currently always invokes a rehandle, would not be able to invoke a rehandle inside routes, which would defeat their linearity. Users may intend to perform a rewrite then immediately run the next handler, without re-evaluating all matchers and re-running the route again. However, outside a route, doing this makes sense so that the entire Caddyfile for that site can be evaluated based on the new URI -- this is also crucial, for if routes are executed before rewrite, and rewrite is designed to "kick" a request into a route, rehandling is necessary in order for the route to pick up the rewritten request.

@mholt mholt added this to the 2.0 milestone Dec 2, 2019
@mholt mholt self-assigned this Dec 2, 2019

This comment has been minimized.

Copy link

@francislavoie francislavoie commented Dec 2, 2019

I think it's worth mentioning that this is an alternative to using the handler_order global option, but this also allows mixing both "appearance" and "predefined" orders in the same config.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
2 participants
You can’t perform that action at this time.