Nginx ters proxy + URL yeniden yazma


149

Nginx, 80 numaralı bağlantı noktasında çalışıyor ve bu şekilde /foobağlantı noktası olan proxy URL'lerini tersine çevirmek için kullanıyorum 3200:

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

Bu iyi çalışıyor, ancak 3200başlangıçta gönderilmesini istemediğim bağlantı noktasında bir uygulamam var /foo. Yani - eriştiğimde http://localhost/foo/bar, yalnızca /baruygulamanın aldığı yolun olmasını istiyorum . Böylece bu satırı yukarıdaki konum bloğuna eklemeye çalıştım:

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

Bu, 302 yönlendirmesine neden olur (URL’de değişiklik), ancak 301’i istiyorum. Ne yapmalıyım?


Grafana davasıyla ilgili herhangi bir sorunuz varsa, bu tarifi kullanmalısınız: docs.grafana.org/installation/behind_proxy/…
mohsen saeedi

Yanıtlar:


168

Localhost'a yapılan herhangi bir yönlendirme uzaktaki bir sistemden bir anlam ifade etmiyor (örn. Müşterinin Web tarayıcısı). Böylece yeniden yazma bayrakları kalıcı (301) veya yönlendirme (302) sizin durumunuzda kullanılamaz.

Lütfen şeffaf bir yeniden yazma kuralı kullanarak kurulumu izlemeyi deneyin:

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

curl -iTekrar yazdıklarınızı test etmek için kullanın . Kuralda yapılan çok ince bir değişiklik nginx'in yeniden yönlendirme yapmasına neden olabilir.


1
URL yolu hala bunu yaptığımda app / foo ile başlıyor ...
jeffreyveon

Farklı bir sorun olmalı. Birkaç dakika önce bu senaryoyu başarıyla kopyaladım. Orijinal URL: http: // development / foo / testme / 1234 - Proxy arka ucu olarak bağlanan bir Apache üzerinde çalışan bir PHP betiğinin REQUEST_URI'si: '/ testme / 1234'
Jens Bradler

9
Regex muhtemelen olmalı /foo(.*), aksi takdirde example.com/fooeşleşmeyecek. (ki muhtemelen jeffreyveon'un yaşadığı şeydi)
Benno

Bu tür işler, ancak vücudum proxy_set_body ile ayar yapıyorum kaldırılıyor.
Justin Thomas

/ yeniden yazınız /(.*) / socket.io/ break; SOCKET.IO'YA GÜNÜ KAYDET
user956584

123

Basit yer öneki eşlemesi, proxy_pass yönergesinde bir URI belirlediğiniz sürece, yeniden yazma kuralı kullanmadan çalışır:

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

Direktifin /sonundaki eke dikkat edin proxy_pass. NGINX eşleşen öneki soyun /foove geri kalanı URI'daki arka uç sunucusuna iletir /. Bu nedenle, http://myserver:80/foo/baradresindeki arka uca gönderilecek http://localhost:3200/bar.

Gönderen proxy_pass üzerine nginx docs :

Proxy_pass yönergesi bir URI ile belirtilmişse, sunucuya bir istek iletildiğinde, konumu eşleştiren normalleştirilmiş bir istek URI'sı, yönergede belirtilen bir URI ile değiştirilir:


12
Ben konum / foo / {kime / ekledik daha benim için çalışıyor
Andrei N

Tam olarak aradığım şey buydu!
anbiniyar

6
Bu çok temiz bir çözüm, bu sorunun kanonik bir cevap olmasını tercih ederim.
ralien,

2
Sondaki eğik çizgiyi tutmanın veya kaldırmanın önemini anlamak çok uzun sürdü.
Parvez

5
Bunu //xyzyaparsanız, bu aslında ana bilgisayara geçecektir .
Arşimet Trajano

60

Mutlak en doğru yol ve en iyi uygulama genellikle şöyledir:

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

  • Öndeki ucun arka uçtaki ile aynı olmasını sağlayacak değişkeni otomatik olarak değiştiren sondaki eğik çizgininproxy_pass korkunç önemine dikkat edin . Açık bir yönergeye gerek yok .$uri/foo//rewrite

  • Ayrıca, dikkat sondaki /içindelocation tek noktadan (örneğin bir çalışma sitenizde garip görünümlü URL'ler sahip riski, onsuz - de oldukça önemlidir /fooenek giriş /foo/en).

    Buna ek olarak, arka /bölgesindeki locationile proxy_passbazı sağlayan özel işlem belgelenmesi göre, locationyönerge etkili bir örtülü bir neden location = /foo {return 301 /foo/;}de.

    Dolayısıyla, locationizleyen eğik çizgi ile a'yı yukarıdaki gibi tanımlayarak , yalnızca eğik çizgi sonek URL'lerinin /fooengeçerli olmayacağını değil, /fooizleyen eğik çizgi olmadan da geçerli olmaya devam edeceğinizi garanti edersiniz .


Referans dokümantasyonu:


$argsKaybedilmiş gibi görünüyor : http://frontend/foo?bar=bazvekalet edilecek http://backend/.
Arguların url'nin bir

@Vanuan, bundan emin misin? Oldukça eminim ki $args, yukarıdaki kodu kullanıyorsanız, bunlardan ayrı olduğu gibi yine de uygun şekilde kullanılmalı ve $uriiçinde açık değişkenler kullanmıyorsanız, tekrar monte edilmelidir proxy_pass.
17'de

@cnst Oh, anlıyorum. Ana bilgisayar değişkenini kullanıyorum. Bu karşı sezgisel.
Vanuan

1
@ArchimedesTrajano, /fooyönlendirmek için özel bir işlem olduğundan, hatalısınız, /foo/bu nedenle, arka uçta tuhaf bir şey yapmazsanız, /fooistekleriniz bile yukarıdaki kodla çalışacaktır. (Bu btw, zaten aslında cevabın bir parçasıdır.)
cnst

3
Bu çözüm tüm bu forumlarda kazanıyor gibi görünmekle birlikte, Nginx'in URL'nin kodunu çözeceği ve kod çözülmüş URL'yi proxy sunucusuna geçireceği cevabında belirtilmelidir. Bu nedenle, URL’niz URL kodlu parçaları taşıyorsa bu çözüm işe yaramaz.
kodlama

1

Deneyin

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

veya

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

13
Bu cevap neden yukarıdaki gibi yapılandırılması gerektiğine dair bir açıklama yaparsanız iyi olur.
masegaloeh

Bunu //xyzyaparsanız, bu aslında ana bilgisayara geçecektir .
Arşimet Trajano

1

@Terabuck Henüz bir cevap gönderemediğim için üzgünüm.

Localhost kullanmamalısınız, çünkü uygulamanın bir hosts dosyası bulunan bir sunucuda çalıştığına bağlısınızdır. yerel ana makine yalnızca 127.0.0.1'e varsayılan bir çeviridir. Bu ana bilgisayar dosyalarına sahip olmanız gerektiğini belirten hiçbir şey yok. Sadece bir tane olması çok yaygın.

Geridöngü arabirime sahip olmak yine bağımlı olmak için başka bir yaygın şeydir, ancak yine de ağ yığını üzerindeki geridöngü arabirimine bağımlısınızdır. Bu ikisine sahip olmamak nadir görülen bir durumdur. Bu konuda endişelenirsen. En azından unix / linux'ta soketler için seçeneğiniz vardır. Bu, ağ yığınının yerel ana bilgisayara ulaşması gereğini ortadan kaldıracaktır. Ana bilgisayar işletim sisteminde gerçekleşecek birkaç faktör olduğundan, bu yaklaşıma dikkat edin. Açık dosya sayısı vb.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.