Назад | Перейти на главную страницу

Nginx Redirect через прокси, перезапись и сохранение URL

В 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 веб сервер). Однако с этим все еще есть две проблемы:

Мы ищем решение, которое включает только изменение конфигурации веб-сервера на 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;