In Nginx, the old Apache static file cache configuration no longer works. We will need to write a new one.
We only want to redirect to a static file if a number of conditions are met. With mod_rewrite you can just chain a number of RewriteCond
's together and follow them up with a RewriteRule
. In Nginx there is no way to directly chain together a series of if statements. Nesting is also not allowed. We can however dream up our own variables and use them keep track of the state of things.
In the configuration below, we set the $static
variable to 1, and then set it to 0 if any one of the conditions are not met. The last condition checks if $static
is still 1, and if so, rewrites the request to the static file.
set $static 1;
if ($request_uri ~ "\.(xml|css)$") {
set $static 0;
}
if ($http_pragma = 'no-cache') {
set $static 0;
}
if ($http_cache_control = 'no-cache') {
set $static 0;
}
if ($scheme = 'https') {
set $static 0;
}
if ($http_cookie = 'nc_staticfilecache|be_typo_user') {
set $static 0;
}
if ($request_method = 'POST') {
set $static 0;
}
if ($query_string) {
set $static 0;
}
if (!-f $document_root/typo3temp/tx_ncstaticfilecache/$host${request_uri}index.html ) {
set $static 0;
}
if ($static = 1) {
rewrite .* /typo3temp/tx_ncstaticfilecache/$host${request_uri}index.html break;
return 200;
}
There is one caveat. If you set Nginx to run on another port, then the host header will probably look something like 'www.yourdomain.tld:8080'. The static filecache extension however, does not store the files in a directory that includes the port, so the file will never be found. If you run on a non default port, use something like the following:
if (!-f $document_root/typo3temp/tx_ncstaticfilecache/www.domain.tld${request_uri}index.html ) {
set $static 0;
}
if ($static = 1) {
rewrite .* /typo3temp/tx_ncstaticfilecache/www.domain.tld ${request_uri}index.html break;
return 200;
}
You must place this rewrite configuration right before the rewrite to /index.php:
# serve exising files directly
if (-f $request_filename) {
break;
}
################################
# Place the configuration here #
################################
if (!-f $request_filename) {
rewrite .* /index.php last;
return 200;
}
That's all, you now have a setup that works with nc_staticfilecache. Oh, there is one more thing, although the files are read from disk, which is very fast, they no longer send Expires headers that were stored in the .htaccess files (if you have that feature enabled in the static file cache configuration). It's not really a big deal because we can depend on the 'Last-Modified
' and the 'If-Modified-Since
' headers to take care of business for us. When a new cache file is written, the 'Last-Modified
' header Nginx sends will change and the fresh file will be sent to the browser.
Update, aug 6 10:28
Fixed a TYPO (I can not spell the word 'cache' correctly, and the Nginx documents are nog clear about $http
):
# Wrong:
if ($http_cahce-control = 'no-cache') {
set $static 0;
}
# Right:
if ($http_cache_control = 'no-cache') {
set $static 0;
}
Steffen points out a TYPO. The Nginx documentation on $http
says that you can use any HTTP header by just making it 'lowercase'. This should read 'make lowercase and replace the dashes with underscores'. Thanks Steffen!
Update, aug 6 11:10
Updated the WIKI with a note about converting 'dashes' to 'underscores'.
thanks for the interesting article.
There's a small typo in your configuration:
$http_cahce-control
Regards
Steffen
I'm still learning to type TYPOFree after all those years . . . ;-)
I'll try to update the docs on the Nginx wiki as soon as my email address gets confirmed.
nginx -> apache2
are you sure that your tests for the files in tx_nc* is correct?
olivier
if ($request_uri ~ "\.(xml|css|php)$") {
set $static 0;
}
this way they get proxied to the apache.
if ($static = 0) {
proxy_pass https://127.0.0.1:81;
}
thanks this really was something that i was missing.