I want to migrate a concept I’ve used for a long time in Nginx over to Caddy. The idea is that you look for the presence of a file locally, if it isn’t present, you redirect to another site.
I use this when developing locally on large WordPress sites where I don’t want to transfer all the assets from the production site into my development environment.
I don’t want to say how long I’ve been trying to Caddy 2 do this, but nothing I have tried has worked. I spent most of my time trying to use route, but I failed. It was nice to read so much of the docs, but I completely failed. Right now my Caddyfile redirects everything from wp-content/uploads. It looks like this:
example.com {
@uploadNotExists {
path /wp-content/uploads/*
not file # not stonks
}
route {
redir @uploadNotExists http://production-url.com{uri}
# Made it this far? Must not have been
# redirected, so the file must exist.
php_fastcgi unix//var/run/php/php-fpm.sock
file_server
}
}
Hum that’s interesting, I was thinking of a way to bypass WordPress and PHP when using a file cache. It’s a common thing using nginx, but it was not possible (as far as I’m aware anyway) with Caddy 1.
With Caddy 2, it should be possible I think… at least if we can handle bypass for admin user and several URL. I don’t know if someone has already made it work ?
That being said, conceptually speaking it’s bypassing for admin user that’s the tricky part.
Authentication and authorization for WordPress happens in PHP. If you’re aiming to bypass PHP to speed things up… how are you going to authenticate the admin to determine whether cache should be bypassed?
server {
set $cache_uri $request_uri;
# bypass cache if POST requests or URLs with a query string
if ($request_method = POST) {
set $cache_uri 'nullcache';
}
if ($query_string != "") {
set $cache_uri 'nullcache';
}
# bypass cache if URLs containing the following strings
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(index)?.xml|[a-z0-9-]+-sitemap([0-9]+)?.xml)") {
set $cache_uri 'nullcache';
}
# bypass cache if the cookies containing the following strings
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") {
set $cache_uri 'nullcache';
}
# custom sub directory e.g. /blog
set $custom_subdir '';
# default html file
set $cache_enabler_uri '${custom_subdir}/wp-content/cache/cache-enabler/${http_host}${cache_uri}index.html';
location / {
gzip_static on; # this directive is not required but recommended
try_files $cache_enabler_uri $uri $uri/ $custom_subdir/index.php?$args;
}
...
}
Strictly speaking, it’s checking the Cookie header for substrings.
It’s not authenticating the user, but I guess that’s fine - we’re more than happy for some false positives when it comes to disabling the cache. The objective is to get most of the responses cached, yeah?
v1 could discriminate based on this too, but it was tricky to actually get things routed properly based on that. In v2 we have the header and header_regexp matchers as candidates here: Request matchers (Caddyfile) — Caddy Documentation
Basically, going down the list you have there… Caddy v2 can check every single statement, and route appropriately. If you go JSON there’s even the possibility of using vars like they have. Then it just gets sent to a specific root to check for a certain file structure, else it falls back. Yes, this is extremely doable.
You could probably even subroute it to check for gzip sidecars.