I have the following nginx config:
server {
listen 8080;
root /site_root/web;
index index.html;
server_name www.mysite.com;
location / {
try_files $uri @rewriteapp;
}
location @rewriteapp {
rewrite ^(.*)$ /app.php/$1 last;
}
# add headers to static files
location ~* \.(?:ico|css|js|gif|jpe?g|png|svg|woff|ttf|eot)$ {
expires 365d;
add_header Pragma public;
add_header Cache-Control "public";
}
location ~ \.php {
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS $https;
fastcgi_pass unix:/var/run/php-fpm-www.sock;
}
}
Issue This is a standard php application with front controller and some static assets (js/css etc) sitting as files on the filesystem (for arguments sake the location of these files is '/site_root/web/assets').
The intention of the above config is to add 'max-age' headers to these static files to allow browsers to cache them. This works for all files which exist on the filesystem. However I have some assets which are dynamically generated and need to pass through php ('/site_root/web/assets/dynamic/file.uk.js', '/site_root/web/assets/dynamic/file.us.js', '/site_root/web/assets/variable/variable.uk.js').
The issue is that the inclusion of the location directive 'add headers to static files' is causing those dynamic files to 404. How can I either (in order of how desirable each solution is):
Change the location directive to exclude files which don't exist on the server (using try_files/internal?)
Change the location directive to exclude paths which match (a whitelist e.g 'dynamic|variable')
Nginx only uses one location block
This comes down to the fact that nginx will only use one location block. Anything in other location blocks is ignored. In the question any request which matches the "static files" location block, whether the file exists or not, will be processed by that location block only. Whenever there's some ambiguity, I find a useful technique for debugging:
In the headers for a response, the header added from the block which matched will be included:
Solutions
There are many solutions, and you might find this reference material useful to read. One thing to bear in mind is that nginx is intended to be used with prefix routing - that makes life easy for nginx, and you.
Prefix routing
So, if you can do this:
That would be the optimal solution. An extension to that using nested location blocks can also be used, if it's necessary:
Put try files in all location blocks
In the question, there is one location block - so this is an obvious alternative, as mentioned by Micheal:
If you have multiple location blocks though, this gets pretty tedious (though, also probably indicates not using nginx as designed)
404 Front controller
The will-always-work setup, irrespective of what your location blocks look like is to use a 404 front controller. In your case this would mean:
Or similar. Pick the solution that works for you and is the simplest.
Why don't you just pass them on to your application?