модуль ActionController::Redirecting
Публичные методы экземпляров
# File actionpack/lib/action_controller/metal/redirecting.rb, line 95 def redirect_back(fallback_location:, allow_other_host: _allow_other_host, **args) redirect_back_or_to fallback_location, allow_other_host: allow_other_host, **args end
Мягко устаревший псевдоним для redirect_back_or_to, где местоположение fallback_location передается в качестве ключевого аргумента вместо первого позиционного аргумента.
# File actionpack/lib/action_controller/metal/redirecting.rb, line 121
def redirect_back_or_to(fallback_location, allow_other_host: _allow_other_host, **options)
if request.referer && (allow_other_host || _url_host_allowed?(request.referer))
redirect_to request.referer, allow_other_host: allow_other_host, **options
else
# The method level `allow_other_host` doesn't apply in the fallback case, omit and let the `redirect_to` handling take over.
redirect_to fallback_location, **options
end
end Перенаправляет браузер на страницу, которая инициировала запрос (ссылка-источник), если это возможно, в противном случае перенаправляет на указанное значение по умолчанию.
Информация о ссылке-источнике извлекается из HTTP-заголовка Referer (sic) запроса. Этот заголовок является необязательным, и его наличие в запросе зависит от настроек безопасности браузера и предпочтений пользователя. Если в запросе отсутствует этот заголовок, будет использовано значение по умолчанию fallback_location.
redirect_back_or_to({ action: "show", id: 5 })
redirect_back_or_to @post
redirect_back_or_to "http://www.rubyonrails.org"
redirect_back_or_to "/images/screenshot.jpg"
redirect_back_or_to posts_url
redirect_back_or_to proc { edit_post_url(@post) }
redirect_back_or_to '/', allow_other_host: false
Параметры
-
:allow_other_host- Разрешить или запретить перенаправление на хост, отличающийся от текущего хоста, по умолчанию true.
Все остальные параметры, которые можно передать в redirect_to, принимаются как параметры, и поведение идентично.
# File actionpack/lib/action_controller/metal/redirecting.rb, line 82
def redirect_to(options = {}, response_options = {})
raise ActionControllerError.new("Cannot redirect to nil!") unless options
raise AbstractController::DoubleRenderError if response_body
allow_other_host = response_options.delete(:allow_other_host) { _allow_other_host }
self.status = _extract_redirect_to_status(options, response_options)
self.location = _enforce_open_redirect_protection(_compute_redirect_to_location(request, options), allow_other_host: allow_other_host)
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(response.location)}\">redirected</a>.</body></html>"
end Перенаправляет браузер на целевой адрес, указанный в options. Этот параметр может быть любым из следующих:
-
Hash- URL будет сгенерирован вызовом url_for сoptions. -
Record- URL будет сгенерирован вызовом url_for сoptions, который будет ссылаться на именованный URL для этой записи. -
Stringначинающийся сprotocol://(например,http://) или относительной ссылкой протокола (например,//) - Передаётся непосредственно в качестве цели для перенаправления. -
Stringне содержащий протокол - к строке добавляется текущий протокол и хост. -
Proc- блок кода, который будет выполнен в контексте контроллера. Должен вернуть любой параметр, принятыйredirect_to.
Примеры:
redirect_to action: "show", id: 5
redirect_to @post
redirect_to "http://www.rubyonrails.org"
redirect_to "/images/screenshot.jpg"
redirect_to posts_url
redirect_to proc { edit_post_url(@post) }
Перенаправление происходит в виде заголовка 302 Found, если не указано иное с использованием параметра :status.
redirect_to post_url(@post), status: :found redirect_to action: 'atom', status: :moved_permanently redirect_to post_url(@post), status: 301 redirect_to action: 'atom', status: 302
Код состояния может быть стандартным кодом состояния HTTP HTTP Status code в виде целого числа или символом, представляющим строку, преобразованную в нижний регистр, разделённую подчёркиваниями и в виде символа. Обратите внимание, что код состояния должен быть кодом HTTP 3xx, иначе перенаправление не произойдёт.
Если вы используете запросы XHR, отличные от GET или POST, и перенаправляете после запроса, некоторые браузеры будут следовать перенаправлению с использованием исходного метода запроса. Это может привести к нежелательному поведению, например, к двойному DELETE. Чтобы обойти это, вы можете вернуть код состояния 303 See Other, который будет обработан с использованием GET-запроса.
redirect_to posts_url, status: :see_other redirect_to action: 'index', status: 303
Также можно назначить сообщение всплывающего сообщения в рамках перенаправления. Для часто используемых имён всплывающего сообщения существуют два специальных аксессора: alert и notice, а также общий параметр flash.
redirect_to post_url(@post), alert: "Watch it, mister!"
redirect_to post_url(@post), status: :found, notice: "Pay attention to the road"
redirect_to post_url(@post), status: 301, flash: { updated_post_id: @post.id }
redirect_to({ action: 'atom' }, alert: "Something serious happened")
Выражения после redirect_to в нашем контроллере выполняются, поэтому redirect_to не останавливает выполнение функции. Чтобы немедленно завершить выполнение функции после redirect_to, используйте return.
redirect_to post_url(@post) and return
Защита от открытых перенаправлений
По умолчанию Rails защищает от перенаправления на внешние хосты для повышения безопасности вашего приложения, так называемые открытые перенаправления. Примечание: это стало новым поведением по умолчанию в Rails 7.0, после обновления, включите эту защиту, раскомментировав строку с raise_on_open_redirects в config/initializers/new_framework_defaults_7_0.rb.
Здесь redirect_to автоматически проверяет потенциально небезопасный URL:
redirect_to params[:redirect_url]
Возникает исключение UnsafeRedirectError в случае небезопасного перенаправления.
Для разрешения любых внешних перенаправлений передайте `allow_other_host: true`, хотя использование пользовательского параметра в этом случае небезопасно.
redirect_to "https://rubyonrails.org", allow_other_host: true
См. url_from для получения дополнительной информации о том, что представляет собой внутренний и безопасный URL или о том, как перейти к альтернативному URL перенаправления в случае небезопасности.
# File actionpack/lib/action_controller/metal/redirecting.rb, line 169 def url_from(location) location = location.presence location if location && _url_host_allowed?(location) end
Проверяет, является ли переданный location внутренним URL, на который безопасно перенаправить, и возвращает его или nil, если нет. Полезно для обертывания предоставленного пользователем URL перенаправления и перехода к альтернативному URL для перенаправления:
redirect_to url_from(params[:redirect_url]) || root_url
location считается внутренним и безопасным, если он находится на том же хосте, что и request.host:
# If request.host is example.com:
url_from("https://example.com/profile") # => "https://example.com/profile"
url_from("http://example.com/profile") # => "http://example.com/profile"
url_from("http://evil.com/profile") # => nil
Поддомены считаются частью хоста:
# If request.host is on https://example.com or https://app.example.com, you'd get:
url_from("https://dev.example.com/profile") # => nil
ПРИМЕЧАНИЕ: есть сходство с url_for, который генерирует внутренний URL из различных параметров внутри приложения, например, url_for(@post). Однако, url_from предназначен для взятия внешнего параметра для проверки, как в url_from(params[:redirect_url]).
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.