TYPO free

home

fighting for TYPO free code

Enabling nc_staticfilecache in TYPO3 Nginx

5 Aug 2009

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'.

Steffen 6 Aug 2009, 10:11
Hi Michiel,

thanks for the interesting article.

There's a small typo in your configuration:
$http_cahce-control

Regards
Steffen
Michiel 6 Aug 2009, 10:51
Thanks 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.
Olivier 9 Aug 2009, 12:42
hi michiel. thanks for sharing. i am running a slight different setup, where apache is used to do the php stuff

nginx -> apache2

are you sure that your tests for the files in tx_nc* is correct?

olivier
Michiel 9 Aug 2009, 13:48
Yes Olivier, I am sure it all works. I tested the conditions one at a time. You can see examples of static files being served in the 'scripts' section on this site. Just peek in the source of the HTML and scroll all the way down.
Olivier 9 Aug 2009, 18:07
OK. Got it to work. It was the check for the be_typo_user cookie. this cookie gets not destroyed in my typo3 version... i also have slightly changed the way it handles the .php files.

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.
Michiel 9 Aug 2009, 20:48
Ah, the be_typo_user cookie will be destroyed only at the end of your browser 'session'. This means, you need to log out of the backend AND close all your browser windows (quit browser). If you don't the browser cookie will stay. When testing the conditions, it's convenient to use two browsers, one for the backend and one for the frontend.
Commenting is closed for this item