2

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:

  1. If the image is present in /var/www/images/thumb/post1/image1.jpg, serve it directly.
  2. If the image is not there, it needs generating, so pass the request to the API at @backend.
  3. 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.
  4. nginx restarts processing at step 1, which will succeed because the file is now present.
  5. 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?

1 Answer 1

1

Your try_files statement is incorrect, the named location needs to be the last parameter. Besides, the 404 response is generated by the location @backend block, and has nothing to do with the try_files statement in the location /thumb block.

You should try proxy_intercept_errors and error_page to handle the 404 response from the backend.

For example:

location / { try_files $uri @backend1; } location /thumb { root /var/www/images; try_files $uri @backend2; } 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_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; location @backend1 { proxy_pass http://api; } location @backend2 { proxy_intercept_errors on; error_page 404 /missing.png; proxy_pass http://api; } 
5
  • But the missing image applies only to the /thumbs location. The API may return 404s from many other endpoints that should not return images. Commented Sep 19, 2020 at 13:41
  • You could use two separate named locations Commented Sep 19, 2020 at 14:19
  • I don’t get why try_files can’t use a back-end as one of its options to try; isn’t that exactly what it’s for? Commented Sep 19, 2020 at 14:22
  • 1
    The only function of try_files is to test for the existence of local filenames and if they do not exist perform one other function, which may be to branch to a named location, internally rewrite the URI or return a status code. See the documentation for details. Commented Sep 19, 2020 at 14:25
  • We managed to make it work partly based on what you said here. One issue we ran into is that images served via these alternative locations failed to have a correct MIME type assigned (as they are when served statically), so we needed to either create a separate location for every MIME type, or set the MIME type upstream in the API response. Commented Sep 25, 2020 at 7:23

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.