У меня есть работающее веб-приложение на 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
мое приложение upstream возвращает 404 not found /en
. Это имеет смысл, так как у upstream нет пути /en
.
Правильное ли proxy_path
решение? Мне следует переписать "upstream", чтобы он слушал /en
вместо этого, как корневой путь? Или есть директива, которая позволяет мне переписать путь, переданный в upstream?
решение1
Это, вероятно, наиболее эффективный способ сделать то, что вам нужно, без использования каких-либо регулярных выражений:
location = /en {
return 302 /en/;
}
location /en/ {
proxy_pass http://luscious/; # note the trailing slash here, it matters!
}
решение2
Я хотел бы рассмотреть новый ответ на основе регулярных выражений, популярность которого растет.
location ~ ^/en(/?)(.*)$ { # OOPS!
proxy_pass http://luscious/$2$is_args$args; # OOPS!
}
На первый взгляд решение может показаться симпатичным, но оно неверно по нескольким причинам.
Регулярное выражение выше будет соответствовать запросу uri
/enjoy
, перенаправляя его в/joy
upstream. Это действительно так задумано?Запрос на
/en
не приведет ни к каким перенаправлениям, напрямую обслуживая из восходящего потока (почти как если бы вместо этого был сделан/
запрос на , но не совсем). Если вы используете относительные URI в пределах вашей корневой страницы восходящего потока (иначе, почему бы вам не иметь префикс прямо там, внутри восходящих URI?), например (который может ссылаться на специфичный для языка , например), то браузер запросит это как вместо . (Или даже если вы используете абсолютные URI везде, что, если кто-то ссылается на неизвестный полунеобязательный ресурс относительно?) Ой, внезапно сайт может не работать, но только иногда или в крайних случаях./en/
/en/
src="style.css"
url("menu.png")
/style.css
/en/style.css
По моему мнениюболее ранний совет по другому вопросу, уже упомянутый в собственном ответе ОП, использование регулярных выражений предотвращает
proxy_redirect
директиву от значения по умолчаниюdefault
, понизив его доoff
. Это означает, что если восходящий поток отвечает с , когда делаетсяLocation: http://127.0.0.1:8080/en/dir/
запрос на , то это то, что увидит клиент, что, очевидно, не будет работать правильно. (Что было бы особенно иронично для запроса, который изначально предлагает использовать регулярное выражение, однако эта конкретная реализация вместо этого страдает от другой проблемы, как уже упоминалось выше.) Плюс, если вы уже используете/en/dir
/en
upstream
директива, то это может стать еще более уродливым, если вы просто попытаетесь использовать пользовательский, особенно если у вас может быть более одного сервера upstream — как вы можете иметь отдельныйproxy_redirect
для каждого из них? Выproxy_redirect
также можете использовать регулярные выражения внутри , возможно, даже для сопоставления любого хоста, но что, если вы решите дать кросс-доменное перенаправление в будущем?
Чтобы попытаться решить некоторые из вышеперечисленных проблем с помощью одного местоположения на основе регулярных выражений, мы могли бы сделать следующее (обратите внимание, что proxy_pass
нам также пришлось удалить ссылку на сервер из upstream
директивы -based, чтобы сделать задачу 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/;
}
Итак, если вы меня спросите,оригинальное решение с двумя родственными локациями верхнего уровнявсе равно это будет лучшей идеей, чем копать себе кроличью нору, следуя пути регулярных выражений.
решение3
Итак, я нашелответ на 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;
}
}
По сути: передача регулярного выражения в location и передача обратной ссылки в URL proxy_pass.
решение4
Я поигрался с принятым решением выше, но обнаружил, что оно вызывает подозрительные перенаправления для всех CSS и JS-активов. В конце концов, я нашел вдохновение в том, как сделаны конфигурации LinuxServer SWAG Nginx. Вы можете найти ихздесь. Взгляни на pihole.subfolder.conf.sample
.
Таким образом, мое решение выглядит так:
location /en {
return 302 $scheme://$host/en/;
}
location ^~ /en/ {
set $upstream_app lixxxx.members.linode.com;
set $upstream_port 9001;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
rewrite /en(.*) $1 break;
}