I have a PHP script that generates a thumbnail based on an existing path (more info). The basic idea is this:
Given the document root /web/
, an image lives in /web/images/foo.jpg
. When a predefined thumbnail filter named thumb
is requested in the url /web/thumb/foo.jpg
, the PHP script picks it up, and generates a thumbnail on that location, so that it will be served directly via Nginx on the next request.
Now this works with the following (simplified) configuration:
server {
location / {
try_files $uri @rewriteapp;
}
}
Where @rewriteapp
contains the rewrite rule for the application.
The problem is that I want to add an Expires
header to the cached thumbnails. But when I add something like this
location ~* \.(jpe?g|gif|png)$ {
expires 1y;
}
It only works with generated thumbnails, but it returns a 404 on the request that should trigger the @rewriteapp
rule.
I tried adding that last block before or after the first location block, I also tried to include the same try_files
statement inside my location w/ expires block. But none of this works.
How can I add the header to my images?
UPDATE:
The accepted answer below contains a more detailed explanation why this failed. In my case I solved it by replacing the second location block with this:
location /thumb/ {
try_files $uri @rewriteapp;
expires 1y; access_log off; log_not_found off;
}
Best Answer
I have done pretty much exactly what you have done before, i'll copy my nginx vhost code below
basically ordering of your location blocks is somewhat important in this case as per: http://nginx.org/en/docs/http/ngx_http_core_module.html#location
anyway here is my nginx code - you can likely amend this to your local environment:
key things to note: the thumbnails dir doesnt exist on disk (its purely used for the purpose of try_files
this code basically means that for an incoming request say
/thumbnails/small/13909967441.JPG
it will try to look for the file in
/thumbs/small/cache/13909967441.JPG.jpg
(yes i know dual extension - it was a hack for performance what more can i say!) if it finds it, then it serves it with the expires header, if it doesnt find it it then rewrites the request internally to the thumbnailing script configured for that size which generates the image and serves it, the expires header is also added to requests that go through the internal rewrite to the PHP requestthe trick is specifically this line from the documentation:
What that means is, by putting your rewrite/location above your regex rules like the generic one for image files and making sure the flags and having the
^~
or in my case~ ^
(they both equate to same rule) in it prevents the regex rules from matching later on Tthis is because regex rules will normally override non regex matches if its not a=
or^~
matchrequests that hit the
/thumbnails
path will never match the generic regex match for image files because of the above mentioned location that blocks regex matching and the fact that the regex block is after the location block so cant match before it.Update - Based on your nginx code
you would add an expires config line into your location / block as this will set the headers for both the static images AND images coming from the rewrite block, obviously you would either have to remove the images regex location block or add the ^~ operator to your primary location block