Як видалити шлях за допомогою nginx proxy_pass


77

У мене працює веб-додаток на http://example.com/і хочу "встановити" іншу програму на окремому сервері http://example.com/en. Сервери вище за течією і, proxy_passздається, працюють, але для одного питання:

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

Під час відкриття example.com/enповертається мій додаток 404 not found /en. Це має сенс, оскільки вгору за течією немає шляху /en.

Є чи proxy_pathправильне рішення? Чи слід переписати "вище за течією", щоб воно слухало /enзамість цього кореневого шляху? Або є директива, яка дозволяє мені переписати шлях, пройдений уздовж вище за течією?

Відповіді:


133

Це, мабуть, найефективніший спосіб робити те, що ви хочете, без використання регулярних виразів:

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

1
Наскільки я знаю, остання частина все одно проходитиме "/ en" як шлях до проксі, чи не так?
berkes

15
@berkes, ні, це не буде - остання різниця в proxy_passтому, що має значення. Крім того, ця відповідь є правильнішою за ту, яку ви придумали, оскільки вона також гарантує, що вона proxy_redirectзалишається в стані default, тож ви все одно можете використовувати 302et al у своєму бекенді, і змусити її працювати правильно скрізь.
cnst

4
Ах, я пропустив
прорізну

3
АААРГ! НАВЧАЛЬНИЙ СЛОШ!
barrymac

4
3 години пошуку, і так ... Це була остання риса. Дякую, друже!
Лукас П.

12

Я хотів би звернутися до нової відповіді на основі регулярних виразів, яка зростає у популярності.

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

Рішення може здатися милішим на перший погляд, але воно неправильне з кількох причин.

  • Вищенаведений регулярний вираз відповідатиме запиту uri /enjoy, перенаправляючи його /joyвгору за течією. Це дійсно призначено?

  • Запит на запит /enне призведе до переадресації, що безпосередньо подаватиметься /з висхідного потоку (майже як якщо б /en/замість цього був зроблений запит , але не зовсім). Якщо ви використовуєте відносні URI-адреси у вашій кореневій сторінці вгору за течією (інакше, чому б ви не мали /en/префікса прямо там у URI-вгорі потоку?), Наприклад src="style.css"(який може посилатися, наприклад, на мову url("menu.png")), браузер запитає, що як /style.cssзамість /en/style.css. (Або навіть якщо ви використовуєте абсолютні URI скрізь, що робити, якщо хтось відносно посилається на незрозумілий напівфакультативний ресурс?) На жаль, сайт може не працювати, але лише іноді або в крайніх випадках.

  • Відповідно до моїх попередніх порад на інше питання, про яке вже згадував власний відповідь ОП , використання регулярних виразів не дозволяє proxy_redirectдирективі мати значення за замовчуванням default, offа замість цього повернути її . Це означає, що якщо висхідний потік відповість, Location: http://127.0.0.1:8080/en/dir/коли /en/dirбуде зроблений запит , тоді це побачить клієнт, який, очевидно, не працює належним чином. (Що було б особливо іронічно для /enзапиту, який спочатку спонукає до використання регулярних виразів, але ця конкретна реалізація натомість страждає від іншої проблеми, як уже згадувалося вище.) Плюс, якщо ви вже використовуєтеupstreamДиректива, то це може стати додатковим неприємним, якщо ви просто спробуєте перейти з користувацьким, особливо якщо у вас може бути більше одного сервера вгору за течією - як у вас є окремий proxy_redirectдля кожного з них? Ви також можете використовувати регулярні вирази в межах proxy_redirect, можливо, навіть, щоб відповідати будь-якому хосту, але що робити, якщо ви вирішите дати переспрямування між доменами в майбутньому?

Щоб спробувати вирішити деякі з перерахованих вище пунктів за допомогою одного місця на основі регулярних виразів, ми могли б зробити наступне (зауважте, що в цьому proxy_passнам також довелося скинути посилання на сервер із upstreamдирективи -базування , щоб зробити це 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/;
}

Тож, якщо ви запитаєте мене, оригінальне рішення з двома місцями вищого рівня побратимів все- таки було б кращою ідеєю, ніж копати себе в кролячій норі, пройшовши замість цього маршруту.


Це спричиняє виняток:nginx: [emerg] location "/en" is outside location "^/en/?((?<=/).*
Атлан

1
@Athlan, це тому, що ти не повинен насправді використовувати це в першу чергу! Якщо ви все ще хочете, ви можете розмістити це місце за межами regexp.
cnst

розміщення локалізації = / en зовні працює дуже добре! спасибі
Себастьян Вебер

7

Отже, я знайшов відповідь на stackoverflow :

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

В основному: передача регулярного вираження в місце розташування та передача backref до URL-адреси proxy_pass.


Я думаю "proxy_pass соковитий / $ ;" має бути "proxy_pass соковитий / $ 2 "
Зафер

1
@Zafer має рацію, вищевказана відповідь давала мені помилку
відверта

Я змінив відповідь, але не маю під рукою сервера, де я можу спробувати це, банкомат, тому це не підтверджено.
berkes

0

Облік документів Nginx

Щоб передати запит на проксі-сервер HTTP, директива proxy_pass задається всередині місця. Наприклад:

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

Цей приклад конфігурації призводить до передачі всіх запитів, оброблених у цьому місці, на проксі-сервер за вказаною адресою. Цю адресу можна вказати як доменне ім’я або IP-адресу. Адреса також може містити порт:

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

Зауважте, що в першому прикладі вище, за адресою проксі-сервера слідує URI, / link /. Якщо URI вказаний разом з адресою, він замінює частину URI запиту, яка відповідає параметру розташування. Наприклад, тут запит з URI /some/path/page.html буде проксі для http://www.example.com/link/page.html . Якщо адреса вказана без URI, або неможливо визначити частину URI, яку слід замінити, повний URI запиту передається (можливо, змінено).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.