Проблема балансировки нагрузки в nginx с 301 из бэкэнда

Я сталкиваюсь с странной проблемой, для которой я не уверен, является ли это проблемой конфигурации или ошибкой в ​​nginx. Моя настройка - обратный прокси-сервер nginx, имеющий серверы Apache2. Балансировщик нагрузки довольно похож на пример из вики, например, упрощенный:

http {
  upstream myproject {
    server 127.0.0.1:8000;
  }

  server {
    listen 80;
    location / {
      proxy_pass http://myproject;
    }
  }
}

Теперь возникает проблема, например, когда я пытаюсь запросить каталог в Apache, без косой черты в конце URL. Например, клиент запрашивает:

http://apache.myserver.com/somedirectory

Apache ответит HTTP 302, чтобы перенаправить клиента на

http://apache.myserver.com/somedirectory/

Обратите внимание, что URL имеет косую черту в конце, чтобы отметить, что это каталог. Также обратите внимание, что Apache является "умным", используя имя хоста входящего запроса в заголовке перенаправления. Пока все хорошо. Однако при использовании nginx с балансировкой нагрузки этот 301 отправляется клиенту без преобразования обратного имени nginx обратно на реальный сервер / домен. Таким образом, клиент получит следующее:

GET http://nginx.myserver.com/somedirectory
HTTP 301 Moved Permanently
...
Location: http://myproject:8000/somedirectory/

myproject это имя вышестоящего бэкэнда nginx. Это не фактический хост, который может разрешить клиент. Мне кажется, что вместо этого клиент должен был быть перенаправлен на

http://nginx.myserver.com/somedirectory/  

Т.е. имя восходящего бэкэнда должно было быть заменено в заголовке ответа. Это ошибка в nginx или я что-то не так делаю?

2 ответа

Решение

Оказывается, в nginx достаточно много вариантов перенаправления прокси для решения подобных проблем. Я закончил тем, что использовал что-то вроде этого:

location / {
    proxy_pass  http://myproject;
    proxy_set_header Host myproject;
    proxy_redirect http://myproject/ $scheme://$host/;
    proxy_redirect http://myproject:8000/ $scheme://$host/;
}

Это в основном заменяет имя восходящего потока на $host и удаляет порт. В моем случае это работало, потому что я размещаю nginx на портах по умолчанию для HTTP/HTTPS. Если nginx работает на порте не по умолчанию, необходимо что-то вроде этого:

    proxy_redirect http://myproject/ $scheme://$host:$server_port/;
    proxy_redirect http://myproject:8000/ $scheme://$host:$server_port/;

Попробуйте использовать server_name_in_redirect следующим образом:

server_name_in_redirect off;

Если это не сработает, вам может понадобиться что-то сделать с proxy_redirect, хотя похоже, что ваш бэкэнд ведет себя правильно.

Другие вопросы по тегам