Nginx proxy_pass olan yol nasıl kaldırılır


77

Çalışan bir web uygulamam var http://example.com/ve başka bir uygulamayı ayrı bir sunucuya "bağlamak" istiyorum http://example.com/en. Akış yukarı sunucular ve çalışıyor proxy_passgibi görünüyor, ancak bir sorun için:

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location /en {
    proxy_pass http://luscious;
  }
}

Açarken example.com/enyukarı akış uygulamam geri dönüyor 404 not found /en. Bu, giriş yönünün yolu olmadığı için mantıklıdır /en.

proxy_pathdoğru çözüm? "Yukarı akış" ı tekrar yazmalı mıyım, /enbunun yerine kök yolu olarak dinlesin mi? Yoksa akıntıya giden yolu yeniden yazmamı sağlayan bir yönerge var mı?

Yanıtlar:


133

Bu muhtemelen herhangi bir normal ifadeyi kullanmadan istediğinizi yapmanın en etkili yoludur:

location = /en {
    return 302 /en/;
}
location /en/ {
    proxy_pass http://luscious/;  # note the trailing slash here, it matters!
}

1
Bildiğim kadarıyla, son kısım hala "/ en" proxy'ye giden yol olarak geçecekti, değil mi?
berkes

15
@ berkes, hayır, olmaz - sondaki eğik çizgi proxy_passfark yaratan şeydir. Ayrıca, bu cevabı da sağlar, çünkü ile geldi olandan daha doğrudur proxy_redirectkalır defaultyine kullanabilirsiniz, böylece 302Arka uç dahilinde ve diğerleri, ve her yerde düzgün çalışması var.
saat

4
Ah, sondaki eğik çizgiyi
özlüyordum

3
Aaargh! YÜKLEME SIRASI!
barrymac

4
3 saat aradım ve evet ... Sonunda eğikti. Teşekkürler dostum!
Lucas P.

12

Popülerliği artan yeni bir regex tabanlı cevabı ele almak istiyorum.

location ~ ^/en(/?)(.*)$ {  # OOPS!
  proxy_pass http://luscious/$2$is_args$args;  # OOPS!
}

Çözüm ilk bakışta daha sevimli görünebilir, ancak birçok nedenden dolayı yanlış.

  • Yukarıdaki regex /enjoy, onu /joyyukarı akışa yönlendiren bir talebi uri ile eşleştirir . Bu gerçekten amaçlanmış mı?

  • İçin bir istek /endoğrudan bir /yukarı yönden gelenlere hizmet veren herhangi bir yönlendirmeyle sonuçlanmayacak (neredeyse /en/bunun yerine bir istek yapılmış gibi), ancak tam olarak değil. Kök sayfanızda yukarı akışta göreli URI'ler kullanıyorsanız (aksi halde, neden /en/yukarı akış URI'larında ön eke sahip olmuyorsunuz?), Örneğin src="style.css"( örneğin bir dile özgü olabilir url("menu.png")), tarayıcı olarak /style.cssyerine /en/style.css. (Ya da her yerde mutlak URI'lar kullanıyor olsanız bile, birisi nispeten karanlık bir yarı isteğe bağlı kaynağa atıfta bulunursa ne olur?) Hata! Birdenbire, site aniden çalışmayabilir, ancak yalnızca bazen veya son durumlarda çalışır.

  • Daha önceki tavsiyeme göre, OP'nin kendi cevabından daha önce bahsettiğim başka bir soruya göre, düzenli ifadeler kullanmak, proxy_redirectdirektifin varsayılan değere sahip olmasını engeller, yerine defaultaşağıya çevirir off. Bunun anlamı, yukarı yöndeki Location: http://127.0.0.1:8080/en/dir/istek bir istek /en/diryapıldığında yanıt verirse, müşterinin göreceği şeydir, ki bu açıkça doğru çalışmayacaktır. (Hangi /enregex kullanımını en başta talep eden bir istek için özellikle ironik olurdu , ancak bu spesifik uygulama bunun yerine yukarıda belirtildiği gibi başka bir sorundan muzdariptir.) Artı, zaten kullanıyorsanızupstreamyönerge, o zaman özel bir tane ile devam etmeye çalışırsanız, özellikle birden fazla yukarı akış sunucusuna sahipseniz, çirkin hale gelebilir - proxy_redirectbunların her biri için ayrı bir seçeneğiniz var mı? proxy_redirectHerhangi bir konuyu eşleştirmek için belki de içinde normal ifadeler kullanabilirsiniz , ancak sonra gelecekte etki alanları arası bir yönlendirme yapmaya karar verirseniz ne olur?

Yukarıdaki noktalardan bazılarını tek bir regex tabanlı bir konumla ele almaya çalışmak için aşağıdakileri yapabiliriz ( daha da basit hale getirmek proxy_passiçin referansı bir sunucuya upstreamyönlendirilmiş bir yönergeden bırakmamız gerektiğine dikkat edin proxy_redirect):

location ~ ^/en/?((?<=/).*)?$ {
  location = /en { return 302 /en/; }
  proxy_pass http://127.0.0.1:8080/$1$is_args$args;
  proxy_redirect http://127.0.0.1:8080/ /en/;
}

Bu yüzden, bana sorarsanız , iki kardeşin en üst düzeyindeki orijinal çözüm, bunun yerine regex rotasına giderek kendinizi bir tavşan deliğine sokmaktan daha iyi bir fikir olurdu.


Bu bir istisnaya neden olur:nginx: [emerg] location "/en" is outside location "^/en/?((?<=/).*
Athlan

1
@Atlan, çünkü bunu gerçekten en başta kullanmamalısınız! Hala istiyorsan, o yeri regexp'in dışına koyabilirsin.
cnst

dışa yerleştirme = / tr dışına koymak gerçekten iyi çalışıyor! teşekkürler
Sebastian Webber

7

Böylece, cevabı stackoverflow'ta buldum :

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location ~ ^/en(/?)(.*) {
    proxy_pass http://luscious/$2;
  }
}

Temel olarak: bir regex'in yerine yerleştirilmesi ve backref'in proxy_pass URL'sine iletilmesi.


Bence "proxy_pass tatlı / $ ;" "proxy_pass tatlı / $ 2 " olmalıdır
Zafer

1
@ Zafer haklı, yukarıdaki cevap bana bir hata veriyordu
franck

Cevabı değiştirdim, fakat bunu deneyebileceğim bir sunucu yok, ATM, bu yüzden doğrulanmadı.
berkes

0

Nginx belgelerine muhasebe

Bir HTTP proxy sunucusuna istek iletmek için, bir konum içinde proxy_pass yönergesi belirtilir. Örneğin:

location /some/path/ {
    proxy_pass http://www.example.com/link/;
}

Bu örnek yapılandırma, bu konumda işlenen tüm isteklerin belirtilen adresteki proxy sunucusuna geçirilmesine neden olur. Bu adres bir etki alanı adı veya IP adresi olarak belirtilebilir. Adres ayrıca bir bağlantı noktası içerebilir:

location ~ \.php {
    proxy_pass http://127.0.0.1:8000;
}

Yukarıdaki ilk örnekte, proxy sunucusunun adresinin ardından bir URI / link / yazdığını unutmayın. URI adresiyle birlikte belirtilirse, istek URI'sinin konum parametresiyle eşleşen bölümünü değiştirir. Örneğin, burada /some/path/page.html URI ile yapılan istek http://www.example.com/link/page.html adresine iletilecektir . Adres bir URI olmadan belirtilirse veya değiştirilecek URI'nın bir bölümünün belirlenmesi mümkün değilse, tam istek URI'sı iletilir (muhtemelen değiştirilmiş).

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.