Вот моя сокращенная версия nginx vhost conf:
upstream gunicorn {
server 127.0.0.1:8080 fail_timeout=0;
}
server {
listen 80;
listen 443 ssl;
server_name domain.com ~^.+\.domain\.com$;
location / {
try_files $uri @proxy;
}
location @proxy {
proxy_pass_header Server;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 10;
proxy_read_timeout 120;
proxy_pass http://gunicorn;
}
}
Один и тот же сервер должен обслуживать как HTTP, так и HTTPS, однако, когда восходящий поток выдает перенаправление (например, после обработки формы), все запросы HTTPS перенаправляются на HTTP. Единственное, что я нашел, что исправит эту проблему, - это изменение proxy_redirect
на следующее:
proxy_redirect http:// https://;
Это прекрасно работает для запросов, поступающих с HTTPS, но если перенаправление выполняется по HTTP, оно также перенаправляет его на HTTPS, что является проблемой.
От отчаяния я попробовал:
if ($scheme = 'https') {
proxy_redirect http:// https://;
}
Но nginx жалуется, что proxy_redirect
здесь нельзя.
Единственный другой вариант, который я могу придумать, - это определить два сервера отдельно и установить proxy_redirect
только на SSL, но тогда я бы продублировал остальную часть conf (в server
директиву, которую я опустил для простоты). Я знаю, что могу также использовать include
директиву, чтобы исключить избыточность, но я действительно хочу сохранить только один файл conf без каких-либо зависимостей.
Итак, во-первых, есть ли что-то, что мне не хватает, что полностью устранит проблему? Или, во-вторых, если нет, есть ли другой способ (помимо включения внешнего файла) исключить избыточную информацию о конфигурации, чтобы я мог разделить версии HTTP и HTTPS конфигурации сервера?
Что ж, немного вдохновения я попробовал:
proxy_redirect http:// $scheme://;
Что, кажется, помогает. Однако мне это все еще кажется хакерским, поэтому я по-прежнему приветствую любые советы по поводу того, что я делаю неправильно, или менее хакерские способы достижения того же результата.
Другое решение - указать восходящему потоку, является ли запрос HTTP или HTTPS, и выполнить соответствующее перенаправление. Добавление этого в конфигурацию nginx установит заголовок для проверки восходящим потоком.
proxy_set_header X-Scheme $scheme;