Как исправить Sinatra перенаправление https на http под nginx

У меня есть приложение Sinatra, работающее в nginx (используя тонкий как back-proxy), и я использую инструкции redirect '/<path>' в Sinatra. Однако, когда я обращаюсь к сайту под https, эти перенаправления отправляют меня в http://localhost/<path>, а не в https://localhost/<path>, как они должны.

В настоящее время nginx передает управление тонким с помощью этой команды proxy_pass http://thin_cluster, где thin_cluster есть

upstream thin_cluster { server unix:/tmp/thin.cct.0.sock; }

Как я могу это исправить?

Ответы

Ответ 1

Чтобы Sinatra правильно собирала URL-адрес, используемый для перенаправления, он должен иметь возможность определить, использует ли запрос ssl, так что перенаправление может быть выполнено с использованием http или https по мере необходимости.

Очевидно, что фактический вызов тонкому не использует ssl, так как он обрабатывается веб-сервером переднего конца, а прокси-запрос находится в явном виде. Поэтому нам нужен способ сказать Sinatra, что он должен рассматривать запрос как безопасный, хотя на самом деле он не использует ssl.

В конечном итоге код, определяющий, должен ли запрос обрабатываться как безопасный, находится в Rack::Request#ssl? и Rack::Request#scheme. Методы scheme анализируют хэш env, чтобы увидеть, присутствует ли один из нескольких записей. Один из них - HTTP_X_FORWARDED_PROTO, который соответствует заголовку X-Forwarded-Proto HTTP. Если это установлено, то значение используется как схема протокола (http или https).

Итак, если мы добавим этот HTTP-заголовок к запросу, когда он будет проксирован от nginx до конца, Sinatra сможет правильно определить, когда перенаправить на https. В nginx мы можем добавлять заголовки к проксированным запросам с proxy_set_header, и эта схема доступна в переменной $scheme.

Итак, добавив строку

proxy_set_header X-Forwarded-Proto $scheme;

для конфигурации nginx после того, как строка proxy_pass должна заставить ее работать.

Ответ 2

Вы можете заставить все ссылки перейти на https в слое nginx. в nginx.conf:

server{
   listen 80;
   server_name example.com;
   rewrite    ^(.*) https://$server_name$1 redirect;
}    

Хорошо также иметь, чтобы ваши запросы всегда были https