Я пытаюсь поставить обратный прокси перед несколькими внутренними веб-службами.
Nginx настроен и работает правильно для обслуживания запроса. Если я служу только одному location /
в моем файле conf он успешно загружает эту цель proxy_pass, т.е.
location / {
proxy_pass https://internal.ip:port/;
}
Переход к https: // public_proxy_address / отлично загружает этот внутренний ресурс.
Однако, поскольку у меня есть несколько внутренних приложений, я хочу проксировать их все через nginx. Итак, в своем тестировании я изменил conf на следующее:
location /app1 {
proxy_pass https://internal.ip:port/;
}
Имея это на месте, я получаю главную страницу внутреннего индекса приложения / по умолчанию, но источник представления показывает мне, что никакие таблицы стилей ссылок, js или другие ресурсы не переписываются. Поэтому не загружается все содержимое страницы. В Apache я бы, наверное, написал proxyhtmlurlmap ^/resource/ /app1/resource R
. Однако я не могу найти способ добиться этого в nginx.
Я тоже пробовал это, но безрезультатно:
location /app1 {
rewrite /resource(.*?) /app1/resource$1 break;
proxy_pass https://internal.ip:port/;
}
Как мне заставить nginx правильно добавлять целевое местоположение (app1) к запрошенным URL-адресам ресурсов, чтобы они загружались?
Поскольку у меня недостаточно кредитов, я не могу комментировать записи, поэтому здесь мой ответ как отдельная запись.
Я не знаю, почему ОП не согласен, но я думаю, что Мартин Фьордваль правильно определяет проблему и предлагает правильный вариант. Я бы предложил небольшую модификацию его фрагмента, как показано ниже;
location /app1/ {
proxy_set_header Host $http_host/app1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
add_header Pragma "no-cache";
add_header Cache-Control "no-cache";
proxy_pass http://internal.ip:port/;
sub_filter 'action="/' 'action="/app1/';
sub_filter 'href="/' 'href="/app1/';
sub_filter 'src="/' 'src="/app1/';
sub_filter_once off;
}
Итак, если вы уверены, что все ваши относительные URL-адреса, начинающиеся с '/', нуждаются в перенаправлении, приведенное выше добавит '/ app1 /' ко всем и заставит их перехватить блок 'location / app1 /' при ссылке. Затем вы можете просмотреть исходный код страницы и подтвердить, что происходит перезапись.
Вам также, вероятно, понадобится весь или хотя бы часть шабанга 'proxy_set_header', особенно бит 'proxy_set_header Host $ http_host / app1'.
В итоге я просто перешел на прокси на основе поддоменов. Основы выглядят так:
server {
listen 443 ssl;
ssl on;
ssl_cert <cert>;
ssl_key <key>;
server_name appname1.public.com;
location / {
proxy_pass https://internalapp1.ip:port
}
}
server {
listen 443 ssl;
ssl on;
ssl_cert <cert>;
ssl_key <key>;
server_name appname2.public.com;
location / {
proxy_pass https://internalapp2.ip:port
}
}
Это устраняет необходимость в прямой переписывании URL-адресов или ресурсов.
Если я правильно понимаю вашу проблему, похоже, проблема в том, что ваше приложение считает, что оно размещено в корневом uri /
хотя на самом деле он размещен в /app1
и просто об этом не говорят. Nginx обычно не изменяет ответ ваших бэкэндов, чего вы ожидаете, однако это возможно.
Сначала вы хотите проверить, есть ли в вашем приложении опция конфигурации, в которой вы можете определить корневой uri. Если есть, то это, безусловно, самое простое решение.
Если вы ничего не можете найти, вы можете использовать модуль замены чтобы заменить URL-адреса в HTML. Обратите внимание, что для того, чтобы это сработало, вам необходимо отключить кодирование GZIP на бэкэнде, чтобы nginx мог видеть несжатый HTML.
Пример того, как может выглядеть ваш подфильтр
location /app1 {
sub_filter '<a href="/resource/' '<a href="/app1/resource/';
sub_filter_once off;
proxy_pass https://internal.ip:port/;
}
Вы указали один абсолютный URL-адрес в своем местоположении, а не URL-адрес страницы и всех ресурсов, которые она использует. Вам необходимо указать регулярное выражение, которое начинается с этого URL-адреса. Что-то вроде этого может сработать (я не тестировал)
location ~ /app1(/.*) {
proxy_pass https://internal.ip:port/;
}
У меня такая же проблема; страница индекса загружалась, но все ресурсы получили 404.
Я заметил, что в локации у меня было: try_files $uri $uri/ =404;
Это возвращает 404 для всех ресурсов. Просто удали его.
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404; <---- Comment out this line.
# Uncomment to enable naxsi on this location
# include /etc/nginx/naxsi.rules
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}