Veiculação de imagens em cache dinamicamente do nginx

Sep 19 2020

Desejo servir miniaturas para imagens, e essas miniaturas são geradas sob demanda, gravadas em disco e, em seguida, quero entregá-las ao nginx para veiculação.

Minha pasta raiz para miniaturas é /var/www/images. Quando recebo uma solicitação de /thumb/post1/image1.jpg, desejo processá-la assim:

  1. Se a imagem estiver presente em /var/www/images/thumb/post1/image1.jpg, exiba-a diretamente.
  2. Se a imagem não estiver lá, será necessário gerá-la, então passe a solicitação à API em @backend.
  3. A API gera a imagem e a grava na pasta de miniaturas e, em seguida, entrega o caminho de volta ao nginx usando um X-Accel-Redirectcabeçalho.
  4. O nginx reinicia o processamento na etapa 1, que será bem-sucedida porque o arquivo agora está presente.
  5. Se o item para o qual o thumb foi solicitado não existir, a API retornará um 404 e o nginx deverá exibir uma imagem de espaço reservado localizada em /var/www/images/missing.png.

Minha configuração nginx se parece com isto:

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

Minhas miniaturas são mantidas fora da pasta do projeto, então preciso de uma rootdiretiva no /thumblocal para fazer com que ela procure a imagem. O /local lida com solicitações de API e outros ativos estáticos e, e o /thumblocal faz o mesmo, mas também tem o fallback para missing.png.

Uma peculiaridade: por razões históricas, minha rootpasta geral não é a mesma usada por meu @backendlocal nomeado, no entanto, estou substituindo isso em ambas as locationdiretivas e não há nível superior try_files.

No entanto, isso não funciona. As solicitações de imagens ausentes não são enviadas à API, mas um substituto para uma imagem ausente sim! Se eu remover o fallback, os pedidos que são enviados para a API, mas depois o handoff a x-accel-redirectfalhar, mesmo que o arquivo já existe; quando a imagem em miniatura existe, o nginx não a exibe - apenas acessa a API novamente.

Como isso deve ser configurado?

Respostas

RichardSmith Sep 19 2020 at 13:38

Sua try_filesafirmação está incorreta, o local nomeado precisa ser o último parâmetro. Além disso, a resposta 404 é gerada pelo location @backendbloco e não tem nada a ver com a try_filesinstrução do location /thumbbloco.

Você deve tentar proxy_intercept_errorse error_pagepara lidar com a resposta 404 do backend.

Por exemplo:

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