Sirviendo imágenes en caché dinámicamente desde nginx

Sep 19 2020

Quiero servir miniaturas para imágenes, y estas miniaturas se generan a pedido, se escriben en el disco, luego quiero entregarlas a nginx para que las sirvan.

Mi carpeta raíz para miniaturas es /var/www/images. Cuando recibo una solicitud /thumb/post1/image1.jpg, quiero procesarla así:

  1. Si la imagen está presente en /var/www/images/thumb/post1/image1.jpg, sírvala directamente.
  2. Si la imagen no está allí, es necesario generarla, así que pase la solicitud a la API en @backend.
  3. La API genera la imagen y la escribe en la carpeta de miniaturas, luego le devuelve la ruta a nginx usando un X-Accel-Redirectencabezado.
  4. nginx reinicia el procesamiento en el paso 1, que tendrá éxito porque el archivo ahora está presente.
  5. Si el elemento para el que se solicitó el pulgar no existe, la API devolverá un 404 y nginx debería mostrar una imagen de marcador de posición ubicada en /var/www/images/missing.png.

Mi configuración de nginx se ve así:

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";
  }
}

Mis miniaturas se mantienen fuera de la carpeta del proyecto, por lo que necesito una rootdirectiva en la /thumbubicación para que busque la imagen allí. La /ubicación maneja solicitudes de API y otros activos estáticos y la /thumbubicación hace lo mismo, pero también tiene el respaldo missing.png.

Una peculiaridad: por razones históricas, mi rootcarpeta general no es la misma que la utilizada por mi @backendubicación nombrada, sin embargo, estoy anulando eso en ambas locationdirectivas, y no hay un nivel superior try_files.

Sin embargo, esto no funciona. Las solicitudes de imágenes que faltan no se envían a la API, ¡pero una reserva para una imagen que falta sí lo hace! Si quito el repliegue, las solicitudes no se envían a la API, pero entonces el traspaso a la x-accel-redirectfalla, aunque el archivo existe ahora; cuando existe la imagen del pulgar, nginx no la sirve, simplemente vuelve a acceder a la API.

¿Cómo se debe configurar esto?

Respuestas

RichardSmith Sep 19 2020 at 13:38

Su try_filesdeclaración es incorrecta, la ubicación nombrada debe ser el último parámetro. Además, la respuesta 404 la genera el location @backendbloque y no tiene nada que ver con la try_filesdeclaración del location /thumbbloque.

Usted debe tratar proxy_intercept_errorsy error_pagemanejar la respuesta 404 desde el servidor.

Por ejemplo:

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;
}