Jak mogę utworzyć lokalizację w Nginx, która działa z AND bez końcowego ukośnika?

46

W tej chwili mam tę konfigurację:

location ~ ^/phpmyadmin/(.*)$
{
        alias /home/phpmyadmin/$1;
}

Jednak jeśli odwiedzę www.mysite.com/phpmyadmin(zauważ brak końcowego ukośnika), nie znajdzie tego, czego szukam 404. Zakładam, ponieważ nie uwzględniam ukośnika końcowego. Jak mogę to naprawić?

Obrabować
źródło
2
Wiem, że to pytanie jest dość stare, jednak chciałbym podkreślić potrzebę zmiany przyjętej odpowiedzi. Niedoświadczeni użytkownicy (ci, którzy będą szukać tego rodzaju kontroli jakości) mogą stworzyć luki w zabezpieczeniach, korzystając z obecnie akceptowanej odpowiedzi.
Bozzy

Odpowiedzi:

34

Może być w wyrażeniu regularnym, którego używasz -

location ~ ^/phpmyadmin/(.*)$

Powyższe będzie pasowało / phpmyadmin /, / phpmyadmin / cokolwiek / else / tutaj, ale nie będzie pasowało / phpmyadmin, ponieważ wyrażenie regularne zawiera ukośnik końcowy.

Prawdopodobnie chcesz czegoś takiego:

location ~ /phpmyadmin/?(.*)$ {
    alias /home/phpmyadmin/$1;
}

Znak zapytania jest kwantyfikatorem wyrażeń regularnych i powinien powiedzieć nginx, aby dopasował zero lub jeden z poprzednich znaków (ukośnik).

Ostrzeżenie: społeczność postrzega to rozwiązanie jako potencjalne zagrożenie bezpieczeństwa

kosiarz
źródło
Dziękuję Ci! I dziękuję również za wyjaśnienie. Przyda się w przyszłości.
Rob
15
Wzór nie jest całkiem poprawny. Może także pasować do ścieżki takiej jak „/ phpmyadmin1234”, oczywiście to nie to, czego chcesz. Rozwiązanie @ kbec jest właściwe.
Miau
3
Przepraszam, że wyraźnie to przegłosowałem, ale komentarz @Meow jest zbyt ważny, aby go zaniedbać. Może to prowadzić do źle skonfigurowanego serwera WWW, który może zawierać dziury w zabezpieczeniach.
Daniel F
34

Lepsze rozwiązanie:

location ~ ^/phpmyadmin(?:/(.*))?$ {
    alias /home/phpmyadmin/$1;
}

Upewnij się, że serwer ma uprawnienia do /home/phpmyadminpierwszego.


Wyjaśnienie różnicy z zaakceptowaną odpowiedzią:

Chodzi o wyrażenia regularne .

Przede wszystkim ^znak oznacza, że ​​chcesz dopasować od początku łańcucha, a nie gdzieś pośrodku. $Za pomocą końcowych pasujących do końca łańcucha.

Te (?:)środki nie-robienia grupę - nie chcemy go w wynikach przechwytywania, ale chcemy prostej grupy niektórych znaków. Grupujemy to w ten sposób, ponieważ chcemy, aby /char był nieistotną częścią ścieżki potomnej, a nie znaczącą częścią ścieżki nadrzędnej.

kbec
źródło
Dlaczego to jest lepsze?
Meekohi
2
@Meow udzielił odpowiedzi na zaakceptowaną odpowiedź
kbec
2
To powinna być zaakceptowana odpowiedź
Yonn Trimoreau,
@ Meekohi napisałem wyjaśnienie
kbec
8

Dlaczego po prostu nie używałbyś

location /phpmyadmin {
    alias /home/phpmyadmin;
}

?

womble
źródło
Ponieważ to nie działało dla mnie. Zobacz tutaj: serverfault.com/questions/375602/…
Rob
1
@Rob Czy próbowałeś tego bez końcowego ukośnika na aliasdyrektywie?
Shane Madden
Jest to właściwie poprawna odpowiedź i właściwy sposób jej wykonania. Po prostu wyklucz ukośnik końcowy i działa to na adresy URL wpisywane zarówno z ukośnikiem końcowym, jak i bez niego. Nie ma potrzeby komplikowania czegokolwiek na Nginxie, to proste, skomplikowane wyrażenia regularne i inne śmieszne rzeczy tylko spowalniają Nginx.
MitchellK,
4
Problem polega na tym, że będzie pasował również do /phpmyadminblahblahblahblahdowolnej kombinacji
Gary Green
6

Wiem, że to stare pytanie, ale dla każdego, kto trafi tutaj przez Google, rozwiązałem je w następujący sposób (odmiana @ kbec, co było całkiem dobre):

location ~ ^/foo(/.*)?$ {
  proxy_pass http://$backend$1$is_args$args
}

Spowoduje to przechwycenie dowolnej odmiany /fooi przekierowanie do /barinnego adresu URL (w tym parametrów). Pokazuję to za pomocą proxy_passdyrektywy, ale to też zadziała alias.

  • /foo -> /bar
  • /foo/ -> /bar/
  • /foo/sub -> /bar/sub
  • /foo/sub1/sub2/?param=value -> /bar/sub1/sub2/?param=value

Działa, ponieważ $1opcjonalnie przechwytuje dodatkowe zasoby i wiodący ukośnik, więc nie będzie przechwytywać takich rzeczy /fooextra/. Przekieruje również odpowiednio obecny lub nieobecny ukośnik końcowy.

dlouzan
źródło
1
Dziękujemy za rozważenie przypadku narożnika, w którym chcemy użyć proxy_pass, a tym samym dbamy o argumenty. Masz moje poparcie.
Daniel F.
2

To przekierowanie spowoduje przepisanie adresów URL tylko z ukośnikiem końcowym i bez niego. Wszystko, co nastąpi po ukośniku, nie zostanie zastąpione.

domain.com/location => przekierowano na domain.com/new/location
domain.com/location => przekierowano na domain.com/new/location
domain.com/location/other => nie przekierowano

server {
  # 301 URL Redirect
  rewrite ^/location/?$ /new/location permanent;
}
Oriol
źródło
1

Czy próbowałeś użyć try_filesdyrektywy?

try_files $uri $uri/ =404;
Prasanth
źródło
0

Zrobiłem to w ten sposób

rewrite ^/promo/?$     http://example.com/promo/page43902.html;
location /promo/ {
    root /var/www;
}
użytkownik3132194
źródło
0

Dlaczego nie po prostu napisać dwa przepisania po prostu:

location ~ ^/phpmyadmin
{
    rewrite /phpmyadmin /home/phpmyadmin/ break;
    rewrite /phpmyadmin/(.*) /home/phpmyadmin/$1 break;
}
千 木 郷
źródło