Nginx przepisuje adres URL tylko wtedy, gdy plik istnieje

13

Muszę napisać regułę przepisywania dla Nginx, aby jeśli użytkownik spróbował przejść do starego adresu URL obrazu:

/images/path/to/image.png

a plik nie istnieje, spróbuj przekierować do:

/website_images/path/to/image.png

TYLKO jeśli obraz istnieje w nowym adresie URL, w przeciwnym razie kontynuuj z 404. Wersja Nginx na naszym hoście nie ma jeszcze plików try_files.

Jose Fernandez
źródło

Odpowiedzi:

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

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

Możesz jednak zaatakować hosta, aby go zaktualizować lub znaleźć lepszego.

Martin Fjordvald
źródło
To przekieruje do / new_images na każde 404, prawda? Nie chcę robić przepisywania, chyba że wiem, że istnieje plik new_images
Jose Fernandez
Sprawdza, czy plik istnieje, a jeśli test się nie powiedzie, następuje przekierowanie do new_images. To, co dzieje się później, nie jest tutaj określone.
tylerl
Obawiam się, że twoja opcja jest uważana za typowe pułapki przez autorów nginx nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/…
riverfall
2
@riverfall Heh, napisałem część tej strony. Moja odpowiedź została napisana 8 lat temu, więc tak, to trochę nieaktualne, ale pierwotne pytanie wyraźnie stwierdzało, że ich gospodarz nie dostarczył najnowszej wersji nginx, więc nie mieli dostępu do plików try_files.
Martin Fjordvald
1
@ Guillaume86 Nie martwiłbym się tym, a przepisanie if + jest całkowicie bezpieczne, a pojedyncze sprawdzenie STAT pliku jest bardzo lekkie. Jest to znacznie szybsze niż przejście do aplikacji zaplecza w celu sprawdzenia trybu konserwacji.
Martin Fjordvald,
6

Nie używaj ifwewnątrz bloku lokalizacji. Mogą się zdarzyć złe rzeczy.

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

$1 staje się nazwą pliku do wypróbowania w dyrektywie try_files, która jest stworzona do tego, co próbujesz osiągnąć.

To, LUB, po prostu przepisz to bez sprawdzania. Jeśli tego obrazu nie ma, i tak otrzymasz 404.

Garet Claborn
źródło
Chociaż odpowiedź ta ściśle nie odpowiada na pytanie („[jeszcze] try_filesnie”), dla przyszłych odwiedzających tutaj, odpowiedź ta zasługuje na więcej głosów pozytywnych.
DerMike,
5

Możesz użyć czegoś takiego (niesprawdzonego w konkretnym przypadku):

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

Który jest w zasadzie alternatywnym sposobem pisania ifinstrukcji zagnieżdżonych , ponieważ nie można zagnieżdżać się w Nginx. Zobacz tutaj oficjalne odniesienia do tego „hacka”.

tmslnz
źródło