Evaluates a group of directives mutually exclusively from other
handle
blocks at the same level of nesting.The
handle
directive is kind of similar to thelocation
directive from nginx config: the first matchinghandle
block will be evaluated. Handle blocks can be nested if needed. Only HTTP handler directives can be used inside handle blocks.
—handle (Caddyfile directive) — Caddy Documentation
So, at each level, only one handle
directive is evaluated, and it’s the first one that matches.
I did note that when setting the same header like that multiple times, the generic one was always selected (header *
), with no regard to either specificity or the order in which they’re set, so the longer-duration ones never seemed to apply.
Putting the longer-duration ones in a handle
block while leaving the generic one on the top level seemed to fix that. This must be something to do with the fact they’re put in a subroute?
Wouldn’t mind @matt’s eyes and input on this one. At the very least, there should be some clear method of exercising control over which header
is executed, so that cases of specific-over-general can be configured. Certainly, having to use handle
groups in this manner to enable specificity of header
directives isn’t ergonomic, nor is it particularly discoverable from documentation.
Anyway, I discovered through testing that the headers don’t need to be handled separately, they just need to be put in any subroute to “beat” the generic header. So here’s the neatest Caddyfile I could come up with that seems to work:
solovyov.net {
encode zstd gzip
header Cache-Control max-age=3600
handle /q/* {
uri strip_prefix /q
root * /mnt/share
file_server browse
}
handle {
header /static/* Cache-Control max-age=31536000
header /favicon.ico Cache-Control max-age=31536000
root * /opt/solovyov.net/www
file_server
}
}