Bagaimana parameter string kueri diteruskan melalui proxy_pass dengan nginx?

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

Cuplikan di atas akan mengarahkan permintaan di mana url menyertakan string "service" ke server lain, tetapi tidak menyertakan parameter kueri.

Alex Luya
sumber

Jawaban:

163

Dari dokumentasi proxy_pass :

Kasus khusus menggunakan variabel dalam pernyataan proxy_pass: URL yang diminta tidak digunakan dan Anda bertanggung jawab penuh untuk membuat sendiri URL target.

Karena Anda menggunakan $ 1 di target, nginx mengandalkan Anda untuk memberitahukan dengan tepat apa yang harus dilewati. Anda dapat memperbaikinya dengan dua cara. Pertama, menghapus awal uri dengan proxy_pass itu sepele:

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

Atau jika Anda ingin menggunakan lokasi regex, cukup sertakan argumennya:

location ~* ^/service/(.*) {
  proxy_pass http://apache/$1$is_args$args;
}
kolbyjack
sumber
1
Saya tidak percaya Anda bisa melakukan yang terakhir. Saya mencoba dan nginx mengeluh kepada saya.
duma
3
Mengeluh bagaimana? Saya baru saja mengujinya di nginx 1.3.4 dan berfungsi dengan baik untuk saya.
kolbyjack
Humm .. Saya tidak bisa mengingatnya sekarang :( Tapi saya rasa ini mungkin terkait dengan "~ *". Namun, saya baru saja memeriksa, dan saya memiliki nginx 1.2.3 (melalui homebrew). Mungkin hanya itu?
duma
"proxy_redirect default" tidak dapat digunakan dengan direktif "proxy_pass" dengan variabel
Jean-Philippe Caruana
1
harus menggunakan penulisan ulang location /service/ { rewrite ^\/service\/(.*) /$1 break; proxy_pass http://apache; }
Andrew Arnautov
27

Saya menggunakan versi pendekatan kedua kolbyjack yang sedikit dimodifikasi, ~bukan ~*.

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

Saya memodifikasi kode @kolbyjack agar berfungsi

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

dengan parameter

location ~ ^/service/?(.*) {
    return 301 http://service_url/$1$is_args$args;
}
Pranav Garg
sumber
1
Perlu diingat bahwa ini akan membuat server mengembalikan respons 301 ke klien sebelum mengalihkan. The proxy_passdirektif di atas melakukan pengalihan pada sisi server.
Luke Peterson
1
Ini akan rusak jika parameter kueri Anda berisi karakter yang dienkode URL (%). Gunakan jawaban Andrew sebagai gantinya.
David Weber
9

Anda harus menggunakan rewrite untuk meneruskan params menggunakan proxy_pass di sini adalah contoh yang saya lakukan untuk penyebaran aplikasi angularjs ke s3

Hosting Situs Statis S3 Merutekan Semua Jalur ke Index.html

diadopsi untuk kebutuhan Anda akan menjadi sesuatu seperti

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

jika Anda ingin berakhir di http://127.0.0.1:8080/query/params/

jika Anda ingin menggunakan http://127.0.0.1:8080/service/query/params/ Anda memerlukan sesuatu seperti

location /service/ {
    rewrite ^\/(.*) /$1 break;
    proxy_pass http://apache;
}
Andrew Arnautov
sumber
1
Sepertinya ini menangani parameter jalur ( /path/params) dengan baik tetapi tidak menangani parameter kueri ( ?query=params)?
Akankah
Ah tidak, kesalahan saya, parameter kueri harus ditambahkan secara otomatis (mereka sedang dalam pengujian saya).
Akankah
2

github inti 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
sumber
1

Untuk mengalihkan Tanpa Query String tambahkan baris di bawah ini di blok Server di bawah baris port mendengarkan:

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

Dengan Query String:

if ($uri ~ .*.containingString$) {
           return 301 https://$host/$uri/?$query_string;
}
Abhishek
sumber
1
Dokumentasi nginx secara eksplisit di hindari untuk digunakan ifjika memungkinkan. Dalam hal ini, solusinya bisa benar menggunakan locationseperti yang ditunjukkan pada jawaban lain.
Andrés Morales
2
Lagi