Измените $request_uri в Nginx

У меня есть несколько приложений, запущенных на сервере Nginx:

http://example.com/app1/ctrl/view
http://example.com/app2/ctrl/view
...

Я хотел бы назначить эти приложения DNS следующим образом:

http://app1.example.com
http://app2.example.com
...

Для этого я пробовал следующий серверный блок:

server {
 listen 80;
 server_name app1.example.com;
 location / {
 proxy_pass http://example.com/app1/$request_uri;
 }
}

Если пользователь не вошел в систему, мое приложение будет перенаправляться на URI:

app1/ctrl/user/login?_next=/app/ctrl/view

По существу $request_uri становится (обратите внимание на удвоенный экземпляр приложения 1):

app1/app1/ctrl/user/login?_next=/app/ctrl/view

Есть ли удобный способ изменить $request_uri или лучший способ обойти эту проблему?

EDIT1

Кажется, я решил проблему со следующим серверным блоком:

server {
 listen 80;
 server_name app1.example.com;
 location / {
 set $new_request_uri $request_uri;
 if ($request_uri ~ ^/app1/(.+)$) {
 set $new_request_uri $1;
 }
 proxy_pass http://example.com/app1/$new_request_uri;
 }
}

Если кто-то знает лучший (или правильный) Nginx) способ сделать это, не стесняйтесь публиковать ответ.

EDIT2

На основании комментариев я также пробовал следующее:

server {
 listen 80;
 server_name app1.example.com;
 location / {
 proxy_pass http://example.com/app1/;
 proxy_redirect /app1/ /;
 }
 location ~ ^/app1/(.+)$ {
 return 301 http://$server_name/$1;
 }
}

Этот экран выглядит лучше на экране, так как он полностью исключает экземпляр App1 в части $request_uri, но у вас должно быть два блока location.

EDIT3

Самый эффективный способ решить мою проблему - это, как показано в этой конфигурации:

server {
 listen 80;
 server_name app1.example.com;
 location / {
 proxy_pass http://example.com/app1/;
 proxy_redirect /app1/ /;
 }
 location /app1/ {
 rewrite ^/app1(.+) $1 permanent;
 }
}

Это связано с тем, что Nginx всегда пытается совместить самый длинный prefix первый, а затем (если модификатор ^~ отсутствует) начинает последовательно обрабатывать regexes до тех пор, пока не будет найден первый regex match, По существу это означает, что все regexes обрабатываются по каждому запросу, независимо от того, найдет ли кто-нибудь из них совпадение, поэтому лучше иметь regexes внутри location директив.

1 ответ

Вам не нужно идти сложным способом. Решение намного проще

server {
 listen 80;
 server_name app1.example.com;
 location / {
 proxy_pass http://app1.example.com/app1/;
 }
 location /app1/ {
 proxy_pass http://app1.example.com/app1/;
 # or
 # rewrite ^/app1(.+) $1 permanent;
 }
}

Nginx позаботится о добавлении /app1/, чтобы запросить и удалить его из заголовка Location.

См. proxy_redirect.

licensed under cc by-sa 3.0 with attribution.