Wie können Abfragezeichenfolgenparameter mit nginx über einen proxy_pass weitergeleitet werden?

114
upstream apache {
   server 127.0.0.1:8080;
}
server{
   location ~* ^/service/(.*)$ {
      proxy_pass http://apache/$1;
      proxy_redirect off;
   }
 }

Das obige Snippet leitet Anforderungen um, bei denen die URL die Zeichenfolge "service" enthält, an einen anderen Server weiter, enthält jedoch keine Abfrageparameter.

Alex Luya
quelle

Antworten:

163

Aus der proxy_pass- Dokumentation:

Ein Sonderfall ist die Verwendung von Variablen in der Anweisung proxy_pass: Die angeforderte URL wird nicht verwendet, und Sie sind vollständig dafür verantwortlich, die Ziel-URL selbst zu erstellen.

Da Sie $ 1 im Ziel verwenden, verlässt sich nginx darauf, dass Sie ihm genau sagen, was er passieren soll. Sie können dies auf zwei Arten beheben. Erstens ist es trivial, den Anfang des Uri mit einem proxy_pass zu entfernen:

location /service/ {
  # Note the trailing slash on the proxy_pass.
  # It tells nginx to replace /service/ with / when passing the request.
  proxy_pass http://apache/;
}

Oder wenn Sie den Regex-Speicherort verwenden möchten, geben Sie einfach die folgenden Argumente an:

location ~* ^/service/(.*) {
  proxy_pass http://apache/$1$is_args$args;
}
Kolbyjack
quelle
1
Ich glaube nicht, dass Sie Letzteres tun können. Ich habe es versucht und Nginx hat sich bei mir beschwert.
Duma
3
Beschwert wie? Ich habe es gerade auf Nginx 1.3.4 getestet und es hat gut für mich funktioniert.
Kolbyjack
Humm .. Ich kann mich jetzt nicht erinnern :( Aber ich habe das Gefühl, dass es mit dem "~ *" zusammenhängt. Allerdings habe ich es gerade überprüft und ich habe Nginx 1.2.3 (durch Homebrew). Vielleicht ist es das?
Duma
"proxy_redirect default" darf nicht mit der Anweisung "proxy_pass" mit Variablen verwendet werden
Jean-Philippe Caruana
1
müssen umschreiben location /service/ { rewrite ^\/service\/(.*) /$1 break; proxy_pass http://apache; }
Andrew Arnautov
27

Ich verwende eine leicht modifizierte Version von Kolbyjacks zweitem Ansatz mit ~anstelle von ~*.

location ~ ^/service/ {
  proxy_pass http://apache/$uri$is_args$args;
}
Sebastian vom Meer
quelle
10

Ich habe den @ kolbyjack-Code geändert, damit er funktioniert

http://website1/service
http://website1/service/

mit Parametern

location ~ ^/service/?(.*) {
    return 301 http://service_url/$1$is_args$args;
}
Pranav Garg
quelle
1
Beachten Sie, dass der Server dadurch vor der Umleitung eine 301-Antwort an den Client zurückgibt. Die proxy_passobige Anweisung führt die Umleitung auf der Serverseite durch.
Luke Peterson
1
Dies wird unterbrochen, wenn Ihre Abfrageparameter URL (%) -codierte Zeichen enthalten. Verwenden Sie stattdessen Andrews Antwort.
David Weber
9

Sie müssen rewrite verwenden, um Parameter mit proxy_pass zu übergeben. Hier ist ein Beispiel, das ich für die Bereitstellung der AngularJS-App an s3 gemacht habe

S3 Static Website Hosting Route Alle Pfade zu Index.html

an Ihre Bedürfnisse angepasst wäre so etwas wie

location /service/ {
    rewrite ^\/service\/(.*) /$1 break;
    proxy_pass http://apache;
}

wenn Sie in http://127.0.0.1:8080/query/params/ landen möchten

Wenn Sie in http://127.0.0.1:8080/service/query/params/ landen möchten, benötigen Sie so etwas wie

location /service/ {
    rewrite ^\/(.*) /$1 break;
    proxy_pass http://apache;
}
Andrew Arnautov
quelle
1
Dies sieht so aus, als würde es mit path params ( /path/params) gut umgehen, aber nicht mit params ( ?query=params)?
Will
Ah nein, mein Fehler, Abfrageparameter sollten automatisch hinzugefügt werden (sie sind in meinen Tests).
Will
2

github gist https://gist.github.com/anjia0532/da4a17f848468de5a374c860b17607e7

#set $token "?"; # deprecated

set $token ""; # declar token is ""(empty str) for original request without args,because $is_args concat any var will be `?`

if ($is_args) { # if the request has args update token to "&"
    set $token "&";
}

location /test {
    set $args "${args}${token}k1=v1&k2=v2"; # update original append custom params with $token
    # if no args $is_args is empty str,else it's "?"
    # http is scheme
    # service is upstream server
    #proxy_pass http://service/$uri$is_args$args; # deprecated remove `/`
    proxy_pass http://service$uri$is_args$args; # proxy pass
}

#http://localhost/test?foo=bar ==> http://service/test?foo=bar&k1=v1&k2=v2

#http://localhost/test/ ==> http://service/test?k1=v1&k2=v2
AnJia
quelle
1

Um ohne Abfragezeichenfolge umzuleiten, fügen Sie die folgenden Zeilen im Serverblock unter der Listenportzeile hinzu:

if ($uri ~ .*.containingString$) {
           return 301 https://$host/$uri/;
}

Mit Abfragezeichenfolge:

if ($uri ~ .*.containingString$) {
           return 301 https://$host/$uri/?$query_string;
}
Abhishek
quelle
1
Die Nginx-Dokumentation ist explizit zu vermeiden, ifwenn möglich zu verwenden. In diesem Fall könnte die Lösung richtig sein, locationwie in anderen Antworten gezeigt.
Andrés Morales
2
Trotzdem
1

arbeitete mit dem Hinzufügen von $ request_uri proxy_pass http: // apache / $ request_uri;

Tobias Sgoff
quelle