Nginx reescribe URL solo si el archivo existe

13

Necesito escribir una regla de reescritura para Nginx para que si un usuario intenta ir a una url de imagen anterior:

/images/path/to/image.png

y el archivo no existe, intente redirigir a:

/website_images/path/to/image.png

SOLO si la imagen existe en la nueva URL, de lo contrario, continúe con la 404. La versión de Nginx en nuestro host todavía no tiene archivos try_files.

Jose fernandez
fuente

Respuestas:

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

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

Sin embargo, es posible que desee molestar a su host para actualizar o encontrar un mejor host.

Martin Fjordvald
fuente
Esto redirigirá a / new_images en cada 404 ¿verdad? No quiero volver a escribir a menos que sepa que existe el archivo new_images
Jose Fernandez
Esto verifica si el archivo existe, y si esa prueba falla, redirige a new_images. Lo que sucede después de eso no se especifica aquí.
tylerl
Me temo que los autores de nginx consideran que su opción es una trampa común
Nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/…
2
@riverfall Heh, escribí parte de esa página. Mi respuesta fue escrita hace 8 años, así que sí, está un poco desactualizada, pero la pregunta original sí indicaba específicamente que su host no proporcionaba una versión reciente de nginx, por lo que no tenían acceso a try_files.
Martin Fjordvald
1
@ Guillaume86 No me preocuparía por eso, una reescritura if + es totalmente segura y una sola comprobación de STAT en un archivo es muy ligera. Es mucho más rápido que ir a una aplicación de fondo para verificar el modo de mantenimiento.
Martin Fjordvald
6

No lo use ifdentro de un bloque de ubicación. Pueden pasar cosas malas.

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

$1 se convierte en el nombre de archivo para probar en la directiva try_files, que está hecha para lo que está tratando de lograr.

Esto, O, simplemente reescríbalo sin verificar. Si esa imagen no está allí, obtendrás un 404 de todos modos.

Garet Claborn
fuente
Si bien esta respuesta estrictamente no responde la pregunta ("[no] try_filestodavía"), para los futuros visitantes que vienen aquí, esta respuesta merece más votos positivos.
DerMike
5

Podría usar algo como esto (no probado para su 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;
    }
}

Que es básicamente una forma alternativa de escribir ifdeclaraciones anidadas , ya que no puede anidar en Nginx. Ver aquí para referencia oficial sobre este "hack".

tmslnz
fuente