diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb index 952aca5bb0293..68241cdbc0ec8 100644 --- a/actionpack/lib/action_controller/metal/redirecting.rb +++ b/actionpack/lib/action_controller/metal/redirecting.rb @@ -106,13 +106,14 @@ def redirect_to(options = {}, response_options = {}) allow_other_host = response_options.delete(:allow_other_host) { _allow_other_host } - self.status = _extract_redirect_to_status(options, response_options) + proposed_status = _extract_redirect_to_status(options, response_options) redirect_to_location = _compute_redirect_to_location(request, options) _ensure_url_is_http_header_safe(redirect_to_location) self.location = _enforce_open_redirect_protection(redirect_to_location, allow_other_host: allow_other_host) self.response_body = "" + self.status = proposed_status end # Soft deprecated alias for #redirect_back_or_to where the `fallback_location` diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index 9f4a49cd16058..8c3959e223ad8 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -203,6 +203,14 @@ def redirect_with_null_bytes redirect_to "\000/lol\r\nwat" end + def redirect_to_external_with_rescue + begin + redirect_to "http://www.rubyonrails.org/", allow_other_host: false + rescue ActionController::Redirecting::UnsafeRedirectError + render plain: "caught error" + end + end + def rescue_errors(e) raise e end private @@ -617,6 +625,11 @@ def test_redirect_to_instrumentation assert_equal "http://test.host/redirect/hello_world", payload[:location] end + def test_redirect_to_external_with_rescue + get :redirect_to_external_with_rescue + assert_response :ok + end + private def with_raise_on_open_redirects old_raise_on_open_redirects = ActionController::Base.raise_on_open_redirects