From 4aabe46341dd6db9bf9bbbbc27c32f467a7c55b7 Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Tue, 9 Oct 2007 23:07:36 +0000 Subject: Add :status to redirect_to allowing users to choose their own response code without manually setting headers. Closes #8297 [codahale, chasgrundy] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7820 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionpack/CHANGELOG | 2 + actionpack/lib/action_controller/base.rb | 31 ++++++++--- actionpack/lib/action_controller/response.rb | 4 +- actionpack/test/controller/redirect_test.rb | 78 ++++++++++++++++++++++++++++ 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 redirect_to :back, 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 = "You are being redirected." 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 -- cgit v1.2.3