Pertanyaan Nginx reverse proxy + penulisan ulang URL


Nginx berjalan di port 80, dan saya menggunakannya untuk membalikkan URL proxy dengan path /foo ke port 3200 cara ini:

location /foo {
                proxy_pass http://localhost:3200;
                proxy_redirect     off;
                proxy_set_header   Host $host;
}

Ini berfungsi dengan baik, tetapi saya memiliki aplikasi di port 3200, yang saya tidak ingin yang pertama /foo untuk dikirim ke. Yaitu - ketika saya mengakses http://localhost/foo/bar, Saya hanya ingin /bar menjadi jalur yang diterima oleh aplikasi. Jadi saya mencoba menambahkan baris ini ke blok lokasi di atas:

rewrite ^(.*)foo(.*)$ http://localhost:3200/$2 permanent;

Ini menyebabkan 302 redirect (perubahan dalam URL), tetapi saya ingin 301. Apa yang harus saya lakukan?


95
2018-04-15 17:31




Jika Anda memiliki masalah dengan kasus Grafana, Anda harus menggunakan resep ini: docs.grafana.org/installation/behind_proxy/… - mohsen saeedi


Jawaban:


Pengalihan apa pun ke localhost tidak masuk akal dari sistem jarak jauh (misalnya browser web klien). Sehingga tulis ulang bendera permanen (301) atau redirect (302) tidak dapat digunakan dalam kasus Anda.

Silakan coba mengikuti pengaturan menggunakan aturan penulisan ulang transparan:

location  /foo {
  rewrite /foo/(.*) /$1  break;
  proxy_pass         http://localhost:3200;
  proxy_redirect     off;
  proxy_set_header   Host $host;
}

Menggunakan curl -i untuk menguji penulisan ulang Anda. Perubahan aturan yang sangat halus dapat menyebabkan nginx melakukan pengalihan.


117
2018-04-15 17:56



Jalur URL masih diawali dengan / foo di aplikasi saya ketika saya melakukannya ... - jeffreyveon
Pasti ada masalah yang berbeda. Saya berhasil mereproduksi skenario ini, beberapa menit yang lalu. URL asli: http: // pengembangan / foo / testme / 1234 - REQUEST_URI dari skrip PHP yang berjalan pada Apache terhubung sebagai proxy back-end: '/ testme / 1234' - Jens Bradler
Regex seharusnya /foo(.*), jika tidak example.com/foo tidak akan dicocokkan. (yang mungkin apa yang dialami jeffreyveon) - Benno
Jenis pekerjaan ini, tetapi tubuh saya yang saya setting dengan proxy_set_body sedang dihapus. - Justin Thomas
tulis ulang /(.*) /socket.io/ break; SIMPAN HARI SAYA UNTUK SOCKET.IO - user956584


Pencocokan prefiks lokasi sederhana berfungsi untuk ini tanpa menggunakan aturan penulisan ulang selama Anda menetapkan URI dalam direktif proxy_pass:

location /foo {
  proxy_pass http://localhost:3200/;
}

Perhatikan tambahannya / pada akhir proxy_pass direktif. NGINX akan menghapus awalan yang cocok /foo dan meneruskan sisanya ke server backend di URI /. Karena itu, http://myserver:80/foo/bar akan memposting ke backend di http://localhost:3200/bar.

Dari Dokumentasi NGINX pada proxy_pass:

Jika direktif proxy_pass ditentukan dengan URI, maka ketika a   permintaan diteruskan ke server, bagian dari URI permintaan yang dinormalisasi   mencocokkan lokasi diganti dengan URI yang ditentukan dalam direktif:


86
2017-09-29 03:30



Bekerja untuk saya daripada saya menambahkan / ke lokasi / foo / { - Andrei N
Inilah tepatnya yang saya cari! - anbiniyar
Ini adalah solusi yang sangat bersih, saya lebih suka ini menjadi jawaban kanonik atas pertanyaan itu. - ralien
Butuh waktu terlalu lama untuk menyadari pentingnya menjaga atau menghapus garis miring trailing. - Parvez
Ini benar-benar akan berlalu //xyz kepada tuan rumah jika Anda melakukan itu. - Archimedes Trajano


Cara paling benar mutlak dan praktik terbaik biasanya adalah sebagai berikut:

location /foo/ {
    proxy_pass http://localhost:3200/; # note the trailing slash!
}

  • Perhatikan pentingnya tertinggal slash di proxy_pass, yang secara otomatis mengubah $uri variabel untuk memiliki /foo/ di bagian depan sesuai dengan / pada backend. Tidak perlu ada yang eksplisit rewrite direktif.

  • Selain itu, perhatikan bahwa trailing / dalam location juga sangat penting - tanpa itu, Anda berisiko memiliki URL yang tampak aneh di situs Anda pada satu titik (mis., kerja /fooen sebagai tambahannya /foo/en).

    Selain itu, trailing / dalam location dengan proxy_pass juga memastikan beberapa penanganan spesial, sesuai dokumentasi dari location direktif, untuk secara efektif menyebabkan implisit location = /foo {return 301 /foo/;} demikian juga.

    Jadi, dengan mendefinisikan a location dengan garis miring di belakang seperti di atas, Anda tidak hanya memastikan bahwa slash-less suffix URLs seperti /fooen tidak akan valid, tetapi juga bahwa a /foo tanpa garis miring akan terus bekerja juga.


Dokumentasi referensi:


30
2017-08-26 21:12



Ini jawaban terbaik di sini! - Mo Friedrich
Sepertinya $args tersesat: http://frontend/foo?bar=baz akan diproksikan ke http://backend/. Perhatikan bahwa arg bukan bagian dari url - Vanuan
@Vanuan, apa kamu yakin tentang itu? Saya cukup yakin $args masih harus ditangani dengan tepat jika Anda menggunakan kode di atas, karena mereka terpisah dari $uri, dan harus dirakit kembali, kecuali jika Anda menggunakan variabel eksplisit di Anda proxy_pass. - cnst
@ArchimedesTrajano, Anda salah, karena ada penanganan khusus untuk /foo untuk mengalihkan ke /foo/, jadi, kecuali Anda melakukan sesuatu yang aneh di backend, bahkan /foo permintaan masih akan berfungsi dengan kode di atas. (Ini sebenarnya sudah menjadi bagian dari jawaban, BTW.) - cnst
Ini adalah jawaban terbaik! Ini harus naik. - phegde


mencoba

location /foo {
    proxy_pass http://localhost:3200/;
    ....

atau

location ^~ /foo {
    proxy_pass http://localhost:3200/;
    ....

0
2018-01-21 16:20



Jawaban ini akan baik jika Anda memberikan beberapa penjelasan mengapa harus dikonfigurasi seperti di atas. - masegaloeh
Ini benar-benar akan berlalu //xyz kepada tuan rumah jika Anda melakukan itu. - Archimedes Trajano