2015-02-23 11 views
16

muszę napisać dyrektywę lokalizacji nginx do żądań proxy do podkatalogu do innego serwera konserwującego urlencoding i usunięcie podkatalogu prefiks.Nginx podkatalogu pass_proxy bez url dekodowania

Oto przykład sztuczne - żądać tak:

http://1.2.3.4/api/save/http%3A%2F%2Fexample.com

powinny uchodzić za

http://abcd.com/save/http%3A%2F%2Fexample.com

Próbowałem kilka różnych sposobów. Here're kilka z nich:

  1. Od this SO question

location /api/ { rewrite ^/api(/.*) $1 break; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass http://abcd.com; } Ale to dekoduje ciąg, więc http://abcd.com dostaje /save/http://example.com

  1. Od another SO question

location /api/ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass http://abcd.com; }

Ale zachowuje podkatalog, więc http://abcd.com otrzymuje /api/save/http%3A%2F%2Fexample.com.

To, co jest potrzebne, znajduje się gdzieś pośrodku. Dziękuję Ci!

UPD: Oto ticket w nginx bug tracker

+0

Możesz spróbować czegoś z lua. Ale przede wszystkim tego nie potrzebujesz, ponieważ według specyfikacji http te adresy są identyczne. –

+0

Lub użyj subdomeny zamiast podkatalogu –

+0

@AlexeyTen Serwer działający na 'http: // abcd.com' przetwarza te żądania w inny sposób i Nie mam nad tym kontroli. Czy znasz link do tego fragmentu specyfikacji http? Nie mogę go znaleźć –

Odpowiedz

23

Ale nie ma łatwego sposobu, aby rozwiązać ten problem Nginx. W nginx trac są pewne błędy, możesz dodać swoje. trac.nginx.org/nginx/.... Myślę więc, że najprostszym sposobem jest posiadanie poddomeny. - Alexey Dziesięć 24 lutego '15 w 14:49

https://trac.nginx.org/nginx/ticket/727

Jeśli chcesz nginx zrobić coś niestandardowego, można to zrobić za pomocą proxy_pass ze zmiennych (a zmienna $ REQUEST_URI, który zawiera unikalny identyfikator URI żądania, wysyłany przez klienta). W takim przypadku Twoim obowiązkiem będzie wykonanie prawidłowych transformacji URI. Pamiętaj jednak, że może to łatwo spowodować problemy z bezpieczeństwem i powinno być wykonywane ostrożnie.

Wyzwanie akceptowane!

location /api/ { 
     rewrite^$request_uri; 
     rewrite ^/api/(.*) $1 break; 
     return 400; 
     proxy_pass http://127.0.0.1:82/$uri; 
    } 

To wszystko, ludzie!


Oto pełny dowód.

Plik konfiguracyjny dla nginx/1.2.1:

server { 
    listen 81; 
    #first, the solution 
    location /api/ { 
     rewrite^$request_uri; 
     rewrite ^/api/(.*) $1 break; 
     return 400; #if the second rewrite won't match 
     proxy_pass http://127.0.0.1:82/$uri; 
    } 
    #next, a few control groups 
    location /dec/ { 
     proxy_pass http://127.0.0.1:82/; 
    } 
    location /mec/ { 
     rewrite ^/mec(/.*) $1 break; 
     proxy_pass http://127.0.0.1:82; 
    } 
    location /nod/ { 
     proxy_pass http://127.0.0.1:82; 
    } 
} 

server { 
    listen 82; 
    return 200 $request_uri\n; 
} 

Oto wyniki prowadzenia kwerend dla każdej lokalizacji:

% echo localhost:81/{api,dec,mec,nod}/save/http%3A%2F%2Fexample.com | xargs -n1 curl 
/save/http%3A%2F%2Fexample.com 
/save/http:/example.com 
/save/http:/example.com 
/nod/save/http%3A%2F%2Fexample.com 
% 

Uwaga że posiadanie że dodatkowym return 400; jest bardzo ważne   — przeciwnym razie Ryzyko związane z bezpieczeństwem (dostęp do plików przez //api itp.), o czym krótko wspomniał Maxim w twoim mandacie na przejazd.


P.S. Jeśli uważasz, że używanie silnika przerobionego jako automatu w stanie skończonym jest super fajne, możesz również sprawdzić mój projekt http://mdoc.su/ lub fork it github.

+1

Serio .. dziękuję za to. Prawdziwa chwila, kiedy to zadziałało zgodnie z oczekiwaniami. Biorąc pod uwagę podobieństwo do istniejących reguł, magia jest oczywiście w przechwytywaniu $ request_uri. – Joe

+0

Aby uniknąć "przepisanego identyfikatora URI o zerowej długości", użyłem przepisać^$ żądanie_uri; przepisać ^/api (/.*) $ 1 break; return 400; proxy_pass http://127.0.0.1:82$uri; –