Browse files

If the first request didn't have any redirection information, then wh…

…en the user is redirected back to that first request, the corresponding controller action should not consult the referer HTTP header for auto-redirection.
  • Loading branch information...
1 parent 1468db5 commit d87aa672ef6cb0fedaea5eccf41246d32cfba916 @FooBarWidget committed Sep 4, 2008
View
11 lib/auto_redirection/controller_extensions.rb
@@ -59,7 +59,7 @@ def clear_redirection_information
# 3. The "Referer" HTTP header.
def attempt_auto_redirect
info = get_redirection_information
- if info.nil?
+ if info.nil? || info.is_a?(NoRedirectionInformation)
return false
end
@@ -140,7 +140,11 @@ def auto_redirect(options = {})
def get_redirection_information
if !@_redirection_information_given
if params.has_key?(:_redirection_information)
- info = RedirectionInformation.load(params[:_redirection_information])
+ if params[:_redirection_information].empty?
+ info = NoRedirectionInformation.new
+ else
+ info = RedirectionInformation.load(params[:_redirection_information])
+ end
elsif flash.has_key?(:_redirection_information)
info = RedirectionInformation.load(flash[:_redirection_information], true, false)
elsif request.headers["Referer"]
@@ -161,7 +165,8 @@ def redirection_information_for_current_request
parameters = params.merge(:_redirection_information =>
current_redirection_info.marshal)
else
- parameters = params
+ parameters = params.merge(:_redirection_information =>
+ NoRedirectionInformation.new.marshal)
end
return ControllerRedirectionInformation.new(
controller_path, action_name, parameters, request.method)
View
18 lib/auto_redirection/redirection_information.rb
@@ -35,7 +35,9 @@ def self.load(data, encrypted = true, ascii7 = true)
end
end
info = Marshal.load(data)
- if info[:url]
+ if info.nil?
+ return NoRedirectionInformation.new
+ elsif info[:url]
return UrlRedirectionInformation.new(info[:url])
else
return ControllerRedirectionInformation.new(
@@ -136,4 +138,18 @@ def ==(other)
end
end
+# May be passed to the next controller action to indicate that the flash
+# and the Referer HTTP header must not be consulted.
+class NoRedirectionInformation < RedirectionInformation
+ def marshal
+ super do
+ Marshal.dump(nil)
+ end
+ end
+
+ def ==(other)
+ return other.is_a?(NoRedirectionInformation)
+ end
+end
+
end # module AutoRedirection
View
14 lib/auto_redirection/testing.rb
@@ -158,6 +158,9 @@ def assert_came_from(path, parameters = nil)
# # But he isn't logged in, so he's redirected to the login page.
# assert_redirected_to '/login/login_form'
#
+ # # User loads the login page.
+ # get('/login/login_form')
+ #
# # User logs in.
# post('/login/process_login', :password => 'secret')
# # The login controller instructs the browser to POST to
@@ -194,9 +197,12 @@ def assert_redirection_with_method(method, path, parameters = nil)
# See +assert_redirection_with_method+ for an example.
def follow_redirection_with_method!
result = parse_post_redirection_page
- params = result[:params].merge(:_redirection_information => result[:redirection_data])
+ params = result[:params]
+ if result[:redirection_data]
+ params = result[:params].merge(:_redirection_information =>
+ result[:redirection_data])
+ end
headers = { :HTTP_REFERER => @_referer }
- old_referer = @_referer
case result[:method]
when :post
post(result[:path], params, headers)
@@ -227,6 +233,10 @@ def get_redirection_information_from_form
return info
end
end
+
+ def clear_referer!
+ @_referer = nil
+ end
private
def add_redirection_information(params)
View
4 test/book_store.rb
@@ -1,6 +1,10 @@
require File.dirname(__FILE__) + '/abstract_unit'
class ApplicationController < ActionController::Base
+ def root_path
+ return '/books/show/123'
+ end
+
private
def logged_in?
return session[:logged_in]
View
3 test/simple_redirections_test.rb
@@ -135,7 +135,8 @@ class SimpleRedirectionTest < ActionController::TestCase
'controller' => @controller.controller_path,
'action' => "action_save_redirection_information",
'hello' => "world",
- 'foo' => ["bar", "baz"]
+ 'foo' => ["bar", "baz"],
+ '_redirection_information' => NoRedirectionInformation.new.marshal
}, info.params)
end
View
18 test/test_methods_test.rb
@@ -19,14 +19,14 @@ class TestMethodsTest < ActionController::IntegrationTest
get('/login/login_form', nil)
assert_response :ok
# The login page knows that he came from /comments/create.
- assert_came_from('/comments/create', { :summary => "hi" })
+ assert_came_from('/comments/create', :summary => "hi")
# He logs in but entered the wrong password.
post("/login/process_login", :password => 'wrong')
# So the login page is redisplayed.
assert_response :ok
# The login page still knows that he came from /comments/create.
- assert_came_from('/comments/create', { :summary => "hi" })
+ assert_came_from('/comments/create', :summary => "hi")
# He logs in, this time with the correct password.
post("/login/process_login", :password => 'secret')
@@ -69,11 +69,23 @@ class TestMethodsTest < ActionController::IntegrationTest
post('/comments/create', :summary => 'hi')
# But he isn't logged in, so he's redirected to the login page.
assert_redirected_to '/login/login_form'
-
+
+ # User loads the login page.
+ get('/login/login_form')
+
# User logs in.
post('/login/process_login', :password => 'secret')
# /comments/create with the original parameters. That is, we are
# dealing with a non-GET redirection.
assert_redirection_with_method(:post, '/comments/create', :summary => 'hi')
+
+ # Follow this instruction, i.e. let us be redirected to
+ # /comments/create.
+ follow_redirection_with_method!
+
+ # NOTE: the first '/comments/create' request didn't have any
+ # redirection information. We're redirected back to '/comments/create',
+ # and in this case we expect it not to consult the HTTP Referer header.
+ assert_equal "Comment 'hi' created!", @response.body
end
end

0 comments on commit d87aa67

Please sign in to comment.