I want to serve thumbnails for images, and these thumbnails are generated on demand, written to disk, then I want to hand them off to nginx to serve.
My root folder for thumbnails is /var/www/images
. When I get a request for /thumb/post1/image1.jpg
, I want to process it like this:
- If the image is present in
/var/www/images/thumb/post1/image1.jpg
, serve it directly. - If the image is not there, it needs generating, so pass the request to the API at
@backend
. - The API generates the image and writes it to the thumbnail folder, then hands the path to it back to nginx using an
X-Accel-Redirect
header. - nginx restarts processing at step 1, which will succeed because the file is now present.
- If the item the thumb was requested for doesn't exist, the API will return a 404, and nginx should serve a placeholder image located at
/var/www/images/missing.png
instead.
My nginx config looks like this:
upstream api {
server localhost:7440 fail_timeout=0;
}
server {
root /var/www/www.example.com/public;
location / {
try_files $uri @backend;
}
location /thumb {
root /var/www/images;
try_files $uri @backend /missing.png;
}
location @backend {
root /var/www/api.example.com/public;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_pass http://api;
#For websocket compatibility
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
My thumbnails are kept outside the project folder, so I need a root
directive in the /thumb
location to make it look there for the image. The /
location handles API requests and other static assets and, and the /thumb
location does the same, but also has the fallback to missing.png
.
One quirk: for historical reasons my overall root
folder is not the same as the one used by my @backend
named location, however, I'm overriding that in both location
directives, and there is no top-level try_files
.
However, this doesn't work. Requests for missing images don't get sent to the API, but a fallback for a missing image does! If I remove the fallback, requests do get sent to the API, but then the handoff to x-accel-redirect
fails, even though the file now exists; when the thumb image does exist, nginx doesn't serve it – it just hits the API again.
How should this be configured?
Your
try_files
statement is incorrect, the named location needs to be the last parameter. Besides, the 404 response is generated by thelocation @backend
block, and has nothing to do with thetry_files
statement in thelocation /thumb
block.You should try
proxy_intercept_errors
anderror_page
to handle the 404 response from the backend.For example: