В Nginx мы пытались перенаправить URL-адрес следующим образом:
http://example.com/some/path -> http://192.168.1.24
где пользователь по-прежнему видит исходный URL-адрес в своем браузере. Как только пользователь будет перенаправлен, скажите, что он щелкнул ссылку на /section/index.html
, мы бы хотели, чтобы это сделало запрос, который приведет к перенаправлению
http://example.com/some/path/section/index.html -> http://192.168.1.24/section/index.html
и снова сохраните исходный URL.
Наши попытки включали различные решения с использованием прокси и правил перезаписи, и ниже показана конфигурация, которая приблизила нас к решению (обратите внимание, что это конфигурация веб-сервера для example.com
веб сервер). Однако с этим все еще есть две проблемы:
http://192.168.1.24
включает /some/path
и поэтому не обслуживает требуемую страницу.Когда вы наводите курсор на ссылку после того, как страница была обслужена, /some/path
отсутствует в URL
server {
listen 80;
server_name www.example.com;
location /some/path/ {
proxy_pass http://192.168.1.24;
proxy_redirect http://www.example.com/some/path http://192.168.1.24;
proxy_set_header Host $host;
}
location / {
index index.html;
root /var/www/example.com/htdocs;
}
}
Мы ищем решение, которое включает только изменение конфигурации веб-сервера на example.com
. Мы можем изменить конфигурацию на 192.168.1.24
(также Nginx), однако мы хотим попытаться избежать этого, потому что нам нужно будет повторить эту настройку для сотен разных серверов, доступ к которым проксируется через example.com
.
Вы должны использовать часть URI в proxy_pass
директива. Кроме того, вы перепутали аргументы порядка proxy_redirect
директива, и, вероятно, она вам вообще не нужна. Nginx имеет разумное значение по умолчанию для этой директивы.
В этом случае ваш location
блок может быть очень простым:
location /some/path/ {
proxy_pass http://192.168.1.24/;
# note this slash -----------^
proxy_set_header Host $host;
}
Во-первых, вы не должны использовать root
директива внутри блока местоположения, это плохая практика. Но в данном случае это не имеет значения.
Попробуйте добавить второй блок местоположения:
location ~ /some/path/(?<section>.+)/index.html {
proxy_pass http://192.168.1.24/$section/index.html;
proxy_set_header Host $host;
}
Это захватывает часть после / some / path / и перед index.html в переменную $ section, которая затем используется для установки назначения proxy_pass. При необходимости вы можете сделать регулярное выражение более конкретным.
Вы можете использовать следующую конфигурацию для 100% бесшовного сопоставления между /some/path/
на интерфейсе и /
на бэкэнде.
Обратите внимание, что это пока единственный ответ, который также беспрепятственно позаботится об абсолютных путях, генерирующих 404 Not Found
ошибок при условии, что правильный HTTP Referer
заголовок отправляется браузером, поэтому все эти гифки должны продолжать загружаться без необходимости изменять базовый HTML (что не только дорого, но и не поддерживается без дополнительных модулей, не скомпилированных по умолчанию).
location /some/path/ {
proxy_pass http://192.168.1.24/; # note the trailing slash!
}
location / {
error_page 404 = @404;
return 404; # this would normally be `try_files` first
}
location @404 {
add_header Vary Referer; # sadly, no effect on 404
if ($http_referer ~ ://[^/]*(/some/path|/the/other)/) {
return 302 $1$uri;
}
return 404 "Not Found\n";
}
Ты можешь найти полное доказательство концепции и минимально жизнеспособный продукт в пределах https://github.com/cnst/StackOverflow.cnst.nginx.conf репозиторий.
Вот тестовый прогон, чтобы подтвердить, что все крайние случаи работают:
curl -v -H 'Referer: http://example.su/some/path/page.html' localhost:6586/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location
> GET /and/more.gif HTTP/1.1
> Referer: http://example.su/some/path/page.html
< HTTP/1.1 302 Moved Temporarily
< Location: http://localhost:6586/some/path/and/more.gif
< Vary: Referer
curl -v localhost:6586/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location
> GET /and/more.gif HTTP/1.1
< HTTP/1.1 404 Not Found
curl -v localhost:6586/some/path/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location -e uri
> GET /some/path/and/more.gif HTTP/1.1
< HTTP/1.1 200 OK
request_uri: /and/more.gif
P.S. Если у вас есть много разных путей для сопоставления, то вместо сравнения регулярных выражений $http_referer
в пределах if
в пределах location @404
, вы можете использовать глобальный map
вместо этого директива.
Также обратите внимание, что конечные косые черты в обоих proxy_pass
, так же хорошо как location
он содержится в, довольно важны согласно соответствующему ответу.
Ссылки:
Когда эта косая черта добавляется к jenkins, проксируемому nginx, вы получаете сообщение об ошибке «Похоже, что ваш обратный прокси-сервер не работает».
proxy_pass http://localhost:8080/;
Remove this -----------------------------^
Следует читать
proxy_pass http://localhost:8080;