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

Обратный прокси-сервер NGINX не загружает ресурсы

Я пытаюсь поставить обратный прокси перед несколькими внутренними веб-службами.

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;
    }