Обратное проксирование на статический сайт не работает

У меня есть сервер nginx, работающий на www.example.com.

В нем я настроил обратный прокси-сервер для моего статического веб-сайта, размещенного на Zeit сейчас.

location /apps/app1/ {
    proxy_pass https://app1.username.now.sh;
}

Однако, когда я посещаю www.example.com/apps/app1, я получаю правильное имя вкладки браузера (в моем случае «React App», поскольку мой статический веб-сайт создан с помощью React, а имя по умолчанию — «React App»).

В консоли браузера я вижу следующие ошибки:

GET https://www.example.com/static/css/1.621e483e.chunk.css net::ERR_ABORTED 404 (Not Found)
GET https://www.example.com/manifest.json 404 (Not Found)
Manifest: Line: 1, column: 1, Unexpected token.

У меня была аналогичная проблема, когда мой статический веб-сайт размещался на Нетлайф. Служба поддержки клиентов Netlify сообщила мне, что они не поддерживают обратное проксирование, но я могу использовать их собственный перенаправляет.

Почему я не могу перенаправить прокси на статический веб-сайт по внешнему URL-адресу? Есть ли способ исправить это?

Обновление 1: В настоящее время я пытаюсь изменить прокси-сервер bluprince13.com/apps/аренда-против-покупки/ на аренда против покупки.bluprince13.now.sh.

🤔 А знаете ли вы, что...
React поддерживает серверный рендеринг (SSR) для улучшения SEO и производительности.


1 210
4

Ответы:

Вероятно, ваш путь не соответствует статике, так как при загрузке он ищет статику в контексте /, а не в /apps/app1/. Таким образом, он не будет соответствовать вашему местоположению и не будет проксировать ваш сайт.

Я бы порекомендовал вам использовать один и тот же путь в вашем прокси и на вашем хосте, иначе вам нужно будет переписать URL-адреса, но вам нужно будет найти каждый шаблон пути для статики, которую обслуживает ваше приложение.

Если это возможно, попробуйте использовать поддомены в контексте / и поместите те же основные заголовки, чтобы помочь вашему приложению лучше разрешаться.

server {
    listen 80;
    server_name app1.example.com;

    location / {
        proxy_set_header HOST $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass https://app1.username.now.sh/;
    }
}

Надеюсь, поможет.

Просто примечание: я думаю, вам следует избегать использования обратного прокси. Вы уверены, что нет другого лучшего решения, такого как установка DNS-записи CNAME?


Должны ли вы это сделать?

Я бы не рекомендовал этого делать по одной простой причине: поскольку вы не контролируете апстрим, а вам прямо сказали, что не поддерживают ваш сценарий, то в любой момент могут принять решение о блокировке вашего прокси-сервера, и тогда ваш весь веб-сайт будет недоступен из-за неподдерживаемой установки. Это то, что произошло со многими людьми, которые пытались починить сломанный Tumblr с помощью Cloudflare в свое время (в те времена очень часто можно было получить пустые страницы из Tumblr, поэтому размещение Cloudflare перед ним фактически ускорило работу). и устранена проблема с пустыми страницами).


Как это сделать.

Однако, если вы все еще хотите сделать это с помощью nginx, это очень просто, и это очень популярный вопрос, связанный с nginx:

По сути, вам просто нужно сопоставить /apps/app1/ на внешнем интерфейсе с / на бэкэнде, и это можно сделать следующим образом — обратите внимание, что косая черта здесь очень важна — в соответствии с http://nginx.org/r/proxy_pass (который относится к нему как к наличию « URI"):

location /apps/app1/ {
    proxy_pass https://app1.username.now.sh/; # DO NOT REMOVE trailing slash!
}

Это возможно, но имеет свои технические недостатки (кроме очевидного соображения, что вы можете нарушить Условия обслуживания восходящего потока).

Вся моя конфигурация выглядит следующим образом:

server {
  server_name localhost;
  listen *:8000;

  location /apps/ {
    sub_filter 'href = "/c' 'href = "/apps/c';
    sub_filter 'href = "/f' 'href = "/apps/f';
    sub_filter 'href = "/m' 'href = "/apps/m';
    sub_filter 'href = "/s' 'href = "/apps/s';
    sub_filter 'src = "/s'  'src = "/apps/s';
    sub_filter_once off;
    proxy_set_header Accept-Encoding "";
    proxy_pass https://renting-vs-buying.bluprince13.now.sh/;
  }
}

Здесь Nginx настроен на замену некоторых частей ответа с помощью своего модуля sub_filter. Мы указываем, какие строки искать и заменять. Поскольку ваш HTML, скорее всего, создан чем-то вроде Webpack и не имеет новых строк, нам нужно повторять замены в каждой строке, поэтому sub_filter_once off.

По поводу Accept-Encoding. Nginx может выполнять замены в ответах text/html. Только. Что означает отсутствие компрессии. И поскольку бэкэнд любит отвечать сжатым контентом, мы просим его не делать этого.

Несколько заметок:

  • статический список фильтров хрупок: ваше приложение может сломаться при добавлении нового префикса на стороне сервера;
  • вы тратите впустую пропускную способность между прокси и серверной частью, потому что использование сжатия невозможно.

Я бы предположил, что лучшим вариантом будет изменить ваше приложение, чтобы оно отвечало с префиксом /apps. И вы бы сразу избежали всей головной боли.


Решено

Вот что сработало для меня, но я понял это только с помощью других парней, которые ответили ниже. Оглядываясь назад, это кажется таким простым, и я чувствую себя глупо из-за того, что сам до этого не додумался!

HTML-код ответа содержит абсолютные URL-адреса для файлов CSS и JS. Браузер изначально загружает HTML-страницу из префикса /apps/app1, но затем пытается загрузить активы из /static, /favicon, /css и т. д. Но там ничего нет!

Проблема в том, что приложение использует абсолютные ссылки. Все, что мне нужно было сделать, это изменить свое приложение, чтобы вместо этого использовать относительные ссылки. С React вы можете легко сделать это, поместив это в свой package.json (см. документы здесь):

"homepage": ".",

Теперь браузер будет правильно загружать активы из /apps/app1/static, /apps/app1/favicon, /apps/app1/css и т. д.