Назад | Перейти на главную страницу

Как я могу исправить переключение перенаправления Sinatra с https на http под nginx?

У меня есть приложение Sinatra, работающее в nginx (с использованием тонкого прокси-сервера), и я использую 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; }

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

url() определяет, следует ли использовать HTTP или HTTPS на основе информации из Sinatra::Request класс, производный от Rack::Request класс. При установке за обратным прокси-сервером, таким как Nginx, обратный прокси-сервер должен вводить некоторые заголовки, сообщающие Rack (и, следовательно, Sinatra) о том, как его видит мир. К сожалению, 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 сообщает Sinatra, что он находится за HTTPS, а не за HTTP, и устанавливает Host: $http_host сообщает Sinatra имя хоста реального сервера. Сейчас, url('/robots.txt') выведет https://hostname/robots.txt. Поскольку нам не нужен Nginx для выполнения замен в наших перенаправлениях, я отключил его явно с помощью proxy_redirect off;. (The X-Forwarded-For просто чтобы Синатра мог определить IP-адрес пользователя.)

Дополнительное преимущество в том, что Sinatra делает все правильно, а не 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)

Вы сможете добиться этого с помощью proxy_redirect директива. Если proxy_redirect default не работает (это должно быть значение по умолчанию), попробуйте что-то вроде этого:

proxy_redirect http://localhost/ https://localhost/;

Попробуй это:

redirect "https://#{request.host}/<path>"

Sinatra легковесный, я полагаю, по умолчанию он не обнаруживает этого.