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.

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

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

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

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

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

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

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


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.