Sometimes your app will need to route a handful of paths to one service and all other paths to another. Caddy's named matchers allow you to define a set of path directives then route them all to a single reverse proxy.
:80 {
    bind 0.0.0.0
    encode zstd gzip
    @webapp {
        path /
        path /posts /posts/*
        path /tags /tags/*
        path /static /static/*
    }
    handle @webapp {
        reverse_proxy webapp:3000
    }
    handle {
        reverse_proxy wordpress:80
    }
}
Alternatively, you can omit the handle blocks:
:80 {
    bind 0.0.0.0
    encode zstd gzip
    @webapp {
        path /
        path /posts /posts/*
        path /tags /tags/*
        path /static /static/*
    }
    reverse_proxy @webapp webapp:3000
    reverse_proxy wordpress:80
}
You may wonder why we're matching most path directives against two different routes, using path /posts /posts/* instead of path /posts*.
Using path /posts* could include paths that you don't intend to proxy. If we used path /posts* and path /static*, we would also match on the following routes:
- /postscript
- /posts-authors
- /static-electricity
- /static-site-generators
This may be the desired behavior in your application, but it's probably not.
 

 
    
Top comments (3)
Thanks, that was very useful!
You could also shorten this config a little, for example to match both
/pathand/path/*, simply write/path*:Hey Vaviloff, I'm glad you found the post useful!
You could shorten the config, but it may proxy requests to
@webappthat you weren't expecting. With the configuration you posted, the following routes would also be proxied to@webapp:/postscript/posts-authors/static-electricity/static-site-generatorsThe config I posted will only match against
/postsor/post/*, which I think is the behavior that most people are expecting.I realize that this isn't obvious, so I added a section about it in my post above. Thank you for the feedback: it made this post better 🙂
Ah, that's actually a very good point indeed, thanks for making a note!