Как я могу исправить перенаправление Sinatra, переключающееся с https на http под nginx?
У меня есть приложение Sinatra, работающее в nginx (использующее thin в качестве бэк-прокси), и я использую redirect '/<path>'
заявления в синатре. Однако, когда я захожу на сайт по 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; }
Как я могу это исправить?
3 ответа
url()
определяет, использовать ли HTTP или HTTPS на основе информации из Sinatra::Request
класс, который является производным от Rack::Request
учебный класс. При размещении за обратным прокси-сервером, таким как Nginx, обратный прокси-сервер должен вводить некоторые заголовки, рассказывающие Рэку (и, следовательно, Синатре) о том, как его видит мир. К сожалению, Nginx не устанавливает эти заголовки по умолчанию, поэтому мы должны сделать это вручную.
Давайте рассмотрим пример проблемной конфигурации.
# Bad configuration
location / {
proxy_pass http://127.0.0.1:9000;
}
Синатра не знает, что за обратным прокси, так url('/robots.txt')
будет генерировать http://127.0.0.1:9000/robots.txt
, Nginx попытается исправить это автоматически по умолчанию proxy_redirect
замещение, в результате чего http://hostname/robots.txt
,
Вот пример предложения прокси из моей собственной конфигурации Nginx.
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-SSL on;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://127.0.0.1:9000;
}
X-Forwarded-SSL: on
говорит Синатре, что он сидит за HTTPS, а не HTTP, и настройка Host: $http_host
сообщает Синатре имя хоста реального сервера. Сейчас, url('/robots.txt')
будет выводить https://hostname/robots.txt
, Поскольку нам не нужен Nginx для выполнения подстановок в наших перенаправлениях, я явно отключил его с помощью proxy_redirect off;
, (The X-Forwarded-For
Синатра также может определить IP-адрес пользователя.)
Дополнительное преимущество - полагаться на то, что Синатра делает все правильно, а не Nginx. proxy_redirect
Дело в том, что вы можете использовать url()
функция в пределах представления и тому подобное.
X-Forwarded-SSL
это только один из нескольких заголовков, которые вы можете установить. HTTPS: on
, X-Forwarded-Scheme: https
, а также X-Forwarded-Proto: https
должно работать просто отлично, тоже. Обратите внимание, что установка схемы на что-то вроде otherproto
не будет работать с Sinatra, так как он проверяет, является ли он HTTPS или нет, и генерирует URL на основе этого логического значения вместо простого копирования схемы.
Если вы заинтересованы в просмотре кода самостоятельно, я рекомендую эти две ссылки в качестве отправной точки:
https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L284 (def uri
) https://github.com/rack/rack/blob/master/lib/rack/request.rb#L199 (def scheme
)
Попробуй это:
redirect "https://#{request.host}/<path>"
Синатра легкий, у него нет определения по умолчанию, я думаю.
Вы должны быть в состоянии достичь этого с помощью директивы proxy_redirect. Если proxy_redirect default
не работает (это должна быть настройка по умолчанию), попробуйте что-то вроде этого:
proxy_redirect http://localhost/ https://localhost/;