Nginx reescreve o URL apenas se o arquivo existir

13

Preciso escrever uma regra de reescrita para o Nginx, para que, se um usuário tentar acessar um URL de imagem antigo:

/images/path/to/image.png

e o arquivo não existe, tente redirecionar para:

/website_images/path/to/image.png

SOMENTE se a imagem existir no novo URL, caso contrário, continue com o 404. A versão do Nginx em nosso host ainda não possui try_files.

Jose Fernandez
fonte

Respostas:

19
location /images/ {
    if (-f $request_filename) {
        break;
    }

    rewrite ^/images/(.*) /new_images/$1 permanent;
}

No entanto, você pode querer incomodar seu host para atualizar ou encontrar um host melhor.

Martin Fjordvald
fonte
Isso será redirecionado para / new_images em todos os 404, certo? Eu não quero reescrever a menos que eu saiba que o arquivo new_images existe #
Jose Fernandez
Isso verifica se o arquivo existe e, se esse teste falhar, é redirecionado para new_images. O que acontece depois disso não está especificado aqui.
31810 Tylerl
Tenho medo de que sua opção é considerado como armadilhas comuns por nginx autores nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/...
Riverfall
2
@riverfall Heh, eu escrevi parte dessa página. Minha resposta foi escrita há 8 anos, então sim, é um pouco desatualizado, mas a pergunta original afirmava especificamente que o host não forneceu uma versão recente do nginx e, portanto, não teve acesso aos try_files.
Martin Fjordvald
1
@ Guillaume86 Eu não me preocuparia com isso, uma reescrita if + é totalmente segura e uma única verificação STAT em um arquivo é muito leve. É muito mais rápido do que acessar um aplicativo de back-end para verificar o modo de manutenção.
Martin Fjordvald 30/08/19
6

Por favor, não use ifdentro de um bloco de localização. Coisas ruins podem acontecer.

location ~* ^/images/(.+)$ {
    root /www;
    try_files /path/to/$1 /website_images/path_to/$1 /any/dir/$1 @your404;
}

$1 torna-se o nome do arquivo para tentar na diretiva try_files, criada para o que você está tentando realizar.

Ou, apenas, reescreva-o sem verificar. Se essa imagem não estiver lá, você receberá um 404 de qualquer maneira.

Garet Claborn
fonte
Embora esta resposta estritamente não responda à pergunta ("[no] try_filesyet"), para futuros visitantes que chegarem aqui, esta resposta merece mais votos.
DerMike 18/04/19
5

Você pode usar algo assim (não testado para o seu caso específico):

location ^/images/(?<imgpath>.*)$ {

    set $no_old  0;
    set $yes_new 0;

    if (!-f $request_filename)
    {
        set $no_old 1;
    }

    if (-f ~* "^/new_path/$imgpath")
    {
        set $yes_new 1$no_old;
    }

    # replacement exists in the new path
    if ($yes_new = 11)
    {
        rewrite ^/images/(.*)$ /new_path/$1 permanent;
    }

    # no image in the new path!
    if ($yes_new = 01)
    {
        return 404;
    }
}

O que é basicamente uma maneira alternativa de escrever ifinstruções aninhadas , pois você não pode aninhar no Nginx. Veja aqui para referência oficial sobre este "hack".

tmslnz
fonte