In che modo i parametri della stringa di query possono essere inoltrati tramite proxy_pass con nginx?


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

Lo snippet sopra reindirizzerà le richieste in cui l'URL include la stringa "servizio" a un altro server, ma non include i parametri di query.

Risposte:


163

Dalla documentazione proxy_pass :

Un caso speciale è l'utilizzo di variabili nell'istruzione proxy_pass: l'URL richiesto non viene utilizzato e l'utente è completamente responsabile della creazione da sé dell'URL di destinazione.

Dato che stai usando $ 1 nel target, nginx fa affidamento su di te per dirgli esattamente cosa passare. Puoi risolvere questo problema in due modi. Innanzitutto, rimuovere l'inizio dell'uri con un proxy_pass è banale:

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

Oppure, se desideri utilizzare la posizione dell'espressione regolare, includi semplicemente gli argomenti:

location ~* ^/service/(.*) {
  proxy_pass http://apache/$1$is_args$args;
}

1
Non credo che tu possa fare quest'ultimo. Ho provato e nginx si è lamentato con me.
duma

3
Si è lamentato come? L'ho appena testato su nginx 1.3.4 e ha funzionato bene per me.
kolbyjack

Humm .. Non riesco a ricordare ora :( Ma mi sento come se fosse correlato al "~ *". Tuttavia, ho appena controllato e ho nginx 1.2.3 (tramite homebrew). Forse è così?
duma

"proxy_redirect default" non può essere utilizzato con la direttiva "proxy_pass" con variabili
Jean-Philippe Caruana

1
devo usare la riscrittura location /service/ { rewrite ^\/service\/(.*) /$1 break; proxy_pass http://apache; }
Andrew Arnautov

27

Uso una versione leggermente modificata del secondo approccio di kolbyjack con ~invece di ~*.

location ~ ^/service/ {
  proxy_pass http://apache/$uri$is_args$args;
}

10

Ho modificato il codice @kolbyjack per farlo funzionare

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

con parametri

location ~ ^/service/?(.*) {
    return 301 http://service_url/$1$is_args$args;
}

1
Tieni presente che questo farà sì che il server restituisca una risposta 301 al client prima del reindirizzamento. La proxy_passdirettiva sopra fa il reindirizzamento sul lato server.
Luke Peterson

1
Ciò si interromperà se i parametri della query contengono caratteri con codifica URL (%). Usa invece la risposta di Andrew.
David Weber

9

devi usare la riscrittura per passare i parametri usando proxy_pass ecco un esempio che ho fatto per la distribuzione dell'app angularjs su s3

Hosting di siti Web statici S3 Instrada tutti i percorsi a Index.html

adottato per le tue esigenze sarebbe qualcosa di simile

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

se vuoi finire in http://127.0.0.1:8080/query/params/

se vuoi finire in http://127.0.0.1:8080/service/query/params/ avrai bisogno di qualcosa di simile

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

1
Sembra che gestisca bene path params ( /path/params) ma non query params ( ?query=params)?
Il

Ah no, errore mio, i parametri di query dovrebbero essere aggiunti automaticamente (sono nei miei test).
Sarà il

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

Per reindirizzare senza stringa di query aggiungere le righe seguenti nel blocco del server sotto la linea della porta di ascolto:

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

Con stringa di query:

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

1
La documentazione di nginx è esplicita da evitare ifquando possibile. In questo caso, la soluzione potrebbe essere corretta usando locationcome mostrato in un'altra risposta.
Andrés Morales

2
comunque una soluzione in più anche se ha degli inconvenienti è meglio
Dmitry Malugin

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.