Jak mogę mieć tę samą regułę dla dwóch lokalizacji w konfiguracji NGINX?

153

Jak mogę mieć tę samą regułę dla dwóch lokalizacji w konfiguracji NGINX?

Wypróbowałem następujące

server {
  location /first/location/ | /second/location/ {
  ..
  ..
  }
}

ale przeładowanie nginx zwróciło ten błąd:

nginx: [emerg] invalid number of arguments in "location" directive**
user1661010
źródło

Odpowiedzi:

239

Próbować

location ~ ^/(first/location|second/location)/ {
  ...
}

Sposób ~użycia wyrażenia regularnego dla adresu URL. Te ^środki, by sprawdzić od pierwszego znaku. Spowoduje to wyszukanie, po którym /nastąpi jedna z lokalizacji, a następnie inna /.

curtwphillips
źródło
37
UWAGA: jeśli zdarza się to często (na przykład tysiące), spowoduje to spadek wydajności z powodu dopasowywania wyrażeń regularnych. Również kolejność dopasowywania jest zasadniczo inna. W wielu „małych” przypadkach będzie zachowywać się tak, jak chcesz, ale należy o tym pamiętać. Osobiście chcę, aby „lokalizacja” Nginx obsługiwała wiele warunków „=” zamiast polegać na regule regex.
Bernard,
7
IMHO, to powinno być bardziej wydajne: lokalizacja ~ (patternOne | patternTwo) {...}
stamster
2
To rozwiązanie nie zadziałało; jednak komentarz @ stamster zrobił; Biegnęnginx/1.13.2
TJ Biddle,
1
jeśli potrzebujesz proxy_passpopracować, zobacz tę odpowiedź: stackoverflow.com/a/46625656/1246870
avs099
1
U mnie to nie działa, gdy oryginalny adres URL kończy się bez ukośnika
Ojciec chrzestny,
88

Inną opcją jest powtórzenie reguł w dwóch lokalizacjach prefiksów przy użyciu dołączonego pliku. Ponieważ lokalizacje prefiksów są niezależne od pozycji w konfiguracji, ich użycie może zaoszczędzić trochę zamieszania podczas późniejszego dodawania innych lokalizacji wyrażeń regularnych. Unikanie lokalizacji wyrażeń regularnych, gdy możesz, pomoże w płynnym skalowaniu konfiguracji.

server {
    location /first/location/ {
        include shared.conf;
    }
    location /second/location/ {
        include shared.conf;
    }
}

Oto przykład shared.conf:

default_type text/plain;
return 200 "http_user_agent:    $http_user_agent
remote_addr:    $remote_addr
remote_port:    $remote_port
scheme:     $scheme
nginx_version:  $nginx_version
";
Cole Tierney
źródło
czy możesz dodać proszę shared.confprzykład i lokalizację?
Дмитрий Кулешов
5
Dodałem przykładowy plik shared.conf. Możesz użyć bezwzględnej ścieżki do shared.conf lub umieścić go w katalogu nginx. W tym przypadku zawiera tylko kilka dyrektyw.
Cole Tierney,
40

Zarówno wyrażenie regularne, jak i dołączone pliki są dobrymi metodami i często ich używam. Ale inną alternatywą jest użycie „nazwanej lokalizacji”, co jest przydatne w wielu sytuacjach - szczególnie tych bardziej skomplikowanych. Oficjalny „Jeśli jest zła” strona pokazuje zasadniczo następującą jako dobry sposób do robienia rzeczy:

error_page 418 = @common_location;
location /first/location/ {
    return 418;
}
location /second/location/ {
    return 418;
}
location @common_location {
    # The common configuration...
}

Te różne podejścia mają zalety i wady. Dużą zaletą wyrażenia regularnego jest to, że możesz przechwytywać części dopasowania i używać ich do modyfikowania odpowiedzi. Oczywiście podobne wyniki można zwykle osiągnąć innymi podejściami, ustawiając zmienną w oryginalnym bloku lub używając map. Wadą podejścia wyrażeń regularnych jest to, że może stać się nieporęczne, jeśli chcesz dopasować różne lokalizacje, a niski priorytet wyrażenia regularnego może po prostu nie pasować do tego, jak chcesz dopasować lokalizacje - nie wspominając o widocznym wpływie na wydajność w niektórych przypadkach z wyrażeń regularnych.

Główną zaletą dołączania plików (o ile wiem) jest to, że jest trochę bardziej elastyczne w kwestii tego, co można dołączyć - na przykład nie musi to być pełny blok lokalizacji. Ale jest też subiektywnie nieco bardziej zagmatwany niż nazwane lokalizacje.

Pamiętaj również, że istnieje powiązane rozwiązanie, którego możesz użyć w podobnych sytuacjach: lokalizacje zagnieżdżone. Chodzi o to, aby zacząć od bardzo ogólnej lokalizacji, zastosować pewną konfigurację wspólną dla kilku możliwych dopasowań, a następnie utworzyć oddzielne zagnieżdżone lokalizacje dla różnych typów ścieżek, które chcesz dopasować. Na przykład może być przydatne zrobienie czegoś takiego:

location /specialpages/ {
    # some config
    location /specialpages/static/ {
        try_files $uri $uri/ =404;
    }
    location /specialpages/dynamic/ {
        proxy_pass http://127.0.0.1;
    }
}
Mikrofon
źródło
7

To krótkie, ale skuteczne i sprawdzone podejście:

location ~ (patternOne|patternTwo){ #rules etc. }

Można więc łatwo mieć wiele wzorców z prostą składnią potoku wskazującą na ten sam blok / reguły lokalizacji.

stamster
źródło