aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG2
-rwxr-xr-xactionpack/lib/action_controller/base.rb31
-rwxr-xr-xactionpack/lib/action_controller/response.rb4
-rwxr-xr-xactionpack/test/controller/redirect_test.rb78
4 files changed, 105 insertions, 10 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index fcce351cff..187b8d118c 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* Add :status to redirect_to allowing users to choose their own response code without manually setting headers. #8297 [codahale, chasgrundy]
+
* Add link_to :back which uses your referrer with a fallback to a javascript link. #7366 [eventualbuddha, tarmo]
* error_messages_for and friends also work with local variables. #9699 [Frederick Cheung]
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 719593c207..0f5604c707 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -987,32 +987,47 @@ module ActionController #:nodoc:
# redirect_to "/images/screenshot.jpg"
# redirect_to :back
#
- # The redirection happens as a "302 Moved" header.
+ # The redirection happens as a "302 Moved" header unless otherwise specified.
+ #
+ # Examples:
+ # 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
#
# When using <tt>redirect_to :back</tt>, if there is no referrer,
# RedirectBackError will be raised. You may specify some fallback
# behavior for this case by rescuing RedirectBackError.
- def redirect_to(options = {}) #:doc:
+ def redirect_to(options = {}, response_status = {}) #:doc:
+
+ if options.is_a?(Hash) && options[:status]
+ status = options.delete(:status)
+ elsif response_status[:status]
+ status = response_status[:status]
+ else
+ status = 302
+ end
+
case options
when %r{^\w+://.*}
raise DoubleRenderError if performed?
- logger.info("Redirected to #{options}") if logger
- response.redirect(options)
+ logger.info("Redirected to #{options}") if logger && logger.info?
+ response.redirect(options, interpret_status(status))
response.redirected_to = options
@performed_redirect = true
when String
- redirect_to(request.protocol + request.host_with_port + options)
+ redirect_to(request.protocol + request.host_with_port + options, :status=>status)
when :back
- request.env["HTTP_REFERER"] ? redirect_to(request.env["HTTP_REFERER"]) : raise(RedirectBackError)
+ request.env["HTTP_REFERER"] ? redirect_to(request.env["HTTP_REFERER"], :status=>status) : raise(RedirectBackError)
when Hash
- redirect_to(url_for(options))
+ redirect_to(url_for(options), :status=>status)
response.redirected_to = options
else
- redirect_to(url_for(options))
+ redirect_to(url_for(options), :status=>status)
end
end
diff --git a/actionpack/lib/action_controller/response.rb b/actionpack/lib/action_controller/response.rb
index 84edafd7bf..1d9f6676ba 100755
--- a/actionpack/lib/action_controller/response.rb
+++ b/actionpack/lib/action_controller/response.rb
@@ -28,8 +28,8 @@ module ActionController
charset.blank? ? nil : charset.strip.split("=")[1]
end
- def redirect(to_url, permanently = false)
- self.headers["Status"] = "302 Found" unless headers["Status"] == "301 Moved Permanently"
+ def redirect(to_url, response_status)
+ self.headers["Status"] = response_status
self.headers["Location"] = to_url
self.body = "<html><body>You are being <a href=\"#{to_url}\">redirected</a>.</body></html>"
diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb
index c7e4c19a0a..7ab1ddde0c 100755
--- a/actionpack/test/controller/redirect_test.rb
+++ b/actionpack/test/controller/redirect_test.rb
@@ -24,6 +24,34 @@ class RedirectController < ActionController::Base
redirect_to :action => "hello_world"
end
+ def redirect_with_status
+ redirect_to({:action => "hello_world", :status => 301})
+ end
+
+ def redirect_with_status_hash
+ redirect_to({:action => "hello_world"}, {:status => 301})
+ end
+
+ def url_redirect_with_status
+ redirect_to("http://www.example.com", :status => :moved_permanently)
+ end
+
+ def url_redirect_with_status_hash
+ redirect_to("http://www.example.com", {:status => 301})
+ end
+
+ def relative_url_redirect_with_status
+ redirect_to("/things/stuff", :status => :found)
+ end
+
+ def relative_url_redirect_with_status_hash
+ redirect_to("/things/stuff", {:status => 301})
+ end
+
+ def redirect_to_back_with_status
+ redirect_to :back, :status => 307
+ end
+
def host_redirect
redirect_to :action => "other_host", :only_path => false, :host => 'other.test.host'
end
@@ -72,6 +100,56 @@ class RedirectTest < Test::Unit::TestCase
assert_equal "http://test.host/redirect/hello_world", redirect_to_url
end
+ def test_redirect_with_no_status
+ get :simple_redirect
+ assert_response 302
+ assert_equal "http://test.host/redirect/hello_world", redirect_to_url
+ end
+
+ def test_redirect_with_status
+ get :redirect_with_status
+ assert_response 301
+ assert_equal "http://test.host/redirect/hello_world", redirect_to_url
+ end
+
+ def test_redirect_with_status_hash
+ get :redirect_with_status_hash
+ assert_response 301
+ assert_equal "http://test.host/redirect/hello_world", redirect_to_url
+ end
+
+ def test_url_redirect_with_status
+ get :url_redirect_with_status
+ assert_response 301
+ assert_equal "http://www.example.com", redirect_to_url
+ end
+
+ def test_url_redirect_with_status_hash
+ get :url_redirect_with_status_hash
+ assert_response 301
+ assert_equal "http://www.example.com", redirect_to_url
+ end
+
+
+ def test_relative_url_redirect_with_status
+ get :relative_url_redirect_with_status
+ assert_response 302
+ assert_equal "http://test.host/things/stuff", redirect_to_url
+ end
+
+ def test_relative_url_redirect_with_status_hash
+ get :relative_url_redirect_with_status_hash
+ assert_response 301
+ assert_equal "http://test.host/things/stuff", redirect_to_url
+ end
+
+ def test_redirect_to_back_with_status
+ @request.env["HTTP_REFERER"] = "http://www.example.com/coming/from"
+ get :redirect_to_back_with_status
+ assert_response 307
+ assert_equal "http://www.example.com/coming/from", redirect_to_url
+ end
+
def test_simple_redirect_using_options
get :host_redirect
assert_response :redirect