Проблема балансировки нагрузки в 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, хотя похоже, что ваш бэкэнд ведет себя правильно.