Обратный прокси-сервер 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 ресурсов, чтобы они загружались?

5 ответов

Поскольку у меня недостаточно кредитов, я не могу комментировать записи, поэтому мой ответ представлен в виде отдельной записи.

Я не знаю, почему ФП не согласен, но я думаю, что Мартин Фьордвал правильно определяет проблему и предлагает правильные вещи. Я бы предложил немного изменить его фрагмент, как показано ниже;

                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 или ресурсов.

Если я правильно понимаю вашу проблему, похоже, проблема в том, что ваше приложение считает, что оно находится в корневом каталоге / в то время как это на самом деле размещено в /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;
    }
Другие вопросы по тегам