Nginx réécrit l'URL uniquement si le fichier existe

13

J'ai besoin d'écrire une règle de réécriture pour Nginx afin que si un utilisateur essaie d'accéder à une ancienne URL d'image:

/images/path/to/image.png

et le fichier n'existe pas, essayez de rediriger vers:

/website_images/path/to/image.png

UNIQUEMENT si l'image existe dans la nouvelle URL, sinon continuez avec le 404. La version de Nginx sur notre hôte n'a pas encore de try_files.

Jose Fernandez
la source

Réponses:

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

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

Cependant, vous voudrez peut-être bugter votre hôte pour mettre à niveau ou trouver un meilleur hôte.

Martin Fjordvald
la source
Cela redirigera vers / new_images tous les 404, non? Je ne veux pas faire la réécriture à moins que je sache que le fichier new_images existe
Jose Fernandez
Cela vérifie si le fichier existe et si ce test échoue, il redirige vers new_images. Ce qui se passe après cela n'est pas spécifié ici.
tylerl
Je crains que votre option est considérée comme pièges par auteurs nginx de
riverfall
2
@riverfall Heh, j'ai écrit une partie de cette page. Ma réponse a été écrite il y a 8 ans, donc oui, elle est un peu dépassée, mais la question d'origine indiquait spécifiquement que leur hôte n'avait pas fourni de version récente de nginx, donc ils n'avaient pas accès à try_files.
Martin Fjordvald
1
@ Guillaume86 Je ne m'en inquiéterais pas, une réécriture if + est totalement sûre et une seule vérification STAT sur un fichier est très légère. C'est beaucoup plus rapide que d'aller dans une application dorsale pour vérifier le mode de maintenance.
Martin Fjordvald
6

Veuillez ne pas utiliser à l' ifintérieur d'un bloc de localisation. De mauvaises choses peuvent arriver.

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

$1 devient le nom de fichier à essayer dans la directive try_files, qui est faite pour ce que vous essayez d'accomplir.

Cela, OU, il suffit de le réécrire sans vérifier. Si cette image n'est pas là, vous obtiendrez de toute façon un 404.

Garet Claborn
la source
Bien que cette réponse ne réponde strictement pas à la question ("[non] pour l' try_filesinstant"), pour les futurs visiteurs venant ici, cette réponse mérite plus de votes positifs.
DerMike
5

Vous pouvez utiliser quelque chose comme ça (non testé pour votre cas spécifique):

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

Ce qui est fondamentalement une manière alternative d'écrire des ifinstructions imbriquées , car vous ne pouvez pas imbriquer dans Nginx. Voir ici pour référence officielle sur ce "hack".

tmslnz
la source