From 9c1e48eaea921efa67fbeed1ff1876dc710f8fd2 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 23 Dec 2008 13:36:05 -0600 Subject: [PATCH] ActionController::VerbPiggybacking middleware --- actionpack/lib/action_controller.rb | 1 + .../lib/action_controller/integration.rb | 11 +++++++++ .../lib/action_controller/middlewares.rb | 2 ++ actionpack/lib/action_controller/request.rb | 20 +++++++--------- .../action_controller/verb_piggybacking.rb | 24 +++++++++++++++++++ actionpack/test/controller/rack_test.rb | 23 ------------------ actionpack/test/controller/request_test.rb | 6 ++--- 7 files changed, 49 insertions(+), 38 deletions(-) create mode 100644 actionpack/lib/action_controller/verb_piggybacking.rb diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 8dc01ba792..3bb755376f 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -74,6 +74,7 @@ def self.load_all! autoload :Translation, 'action_controller/translation' autoload :UrlRewriter, 'action_controller/url_rewriter' autoload :UrlWriter, 'action_controller/url_rewriter' + autoload :VerbPiggybacking, 'action_controller/verb_piggybacking' autoload :Verification, 'action_controller/verification' module Assertions diff --git a/actionpack/lib/action_controller/integration.rb b/actionpack/lib/action_controller/integration.rb index 701b464c99..71e2524e81 100644 --- a/actionpack/lib/action_controller/integration.rb +++ b/actionpack/lib/action_controller/integration.rb @@ -2,6 +2,17 @@ require 'uri' require 'active_support/test_case' +# Monkey patch Rack::Lint to support rewind +module Rack + class Lint + class InputWrapper + def rewind + @input.rewind + end + end + end +end + module ActionController module Integration #:nodoc: # An integration Session instance represents a set of requests and responses diff --git a/actionpack/lib/action_controller/middlewares.rb b/actionpack/lib/action_controller/middlewares.rb index e566c6fef9..793739723f 100644 --- a/actionpack/lib/action_controller/middlewares.rb +++ b/actionpack/lib/action_controller/middlewares.rb @@ -17,3 +17,5 @@ } ) end + +use ActionController::VerbPiggybacking diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb index 2cad7bc84c..d9eb5af849 100755 --- a/actionpack/lib/action_controller/request.rb +++ b/actionpack/lib/action_controller/request.rb @@ -45,8 +45,6 @@ def key?(key) # UnknownHttpMethod is raised for invalid methods not listed in ACCEPTED_HTTP_METHODS. def request_method method = @env['REQUEST_METHOD'] - method = parameters[:_method] if method == 'POST' && !parameters[:_method].blank? - HTTP_METHOD_LOOKUP[method] || raise(UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence}") end memoize :request_method @@ -143,15 +141,15 @@ def etag_matches?(etag) # supplied, both must match, or the request is not considered fresh. def fresh?(response) case - when if_modified_since && if_none_match - not_modified?(response.last_modified) && etag_matches?(response.etag) - when if_modified_since - not_modified?(response.last_modified) - when if_none_match - etag_matches?(response.etag) - else - false - end + when if_modified_since && if_none_match + not_modified?(response.last_modified) && etag_matches?(response.etag) + when if_modified_since + not_modified?(response.last_modified) + when if_none_match + etag_matches?(response.etag) + else + false + end end # Returns the Mime type for the \format used in the request. diff --git a/actionpack/lib/action_controller/verb_piggybacking.rb b/actionpack/lib/action_controller/verb_piggybacking.rb new file mode 100644 index 0000000000..86cde304a0 --- /dev/null +++ b/actionpack/lib/action_controller/verb_piggybacking.rb @@ -0,0 +1,24 @@ +module ActionController + # TODO: Use Rack::MethodOverride when it is released + class VerbPiggybacking + HTTP_METHODS = %w(GET HEAD PUT POST DELETE OPTIONS) + + def initialize(app) + @app = app + end + + def call(env) + if env["REQUEST_METHOD"] == "POST" + req = Request.new(env) + if method = (req.parameters[:_method] || env["HTTP_X_HTTP_METHOD_OVERRIDE"]) + method = method.to_s.upcase + if HTTP_METHODS.include?(method) + env["REQUEST_METHOD"] = method + end + end + end + + @app.call(env) + end + end +end diff --git a/actionpack/test/controller/rack_test.rb b/actionpack/test/controller/rack_test.rb index f58a9c53e5..406e2b2818 100644 --- a/actionpack/test/controller/rack_test.rb +++ b/actionpack/test/controller/rack_test.rb @@ -187,29 +187,6 @@ def test_xml_content_type_verification end end -class RackRequestMethodTest < BaseRackTest - def test_get - assert_equal :get, @request.request_method - end - - def test_post - @request.env['REQUEST_METHOD'] = 'POST' - assert_equal :post, @request.request_method - end - - def test_put - set_content_data '_method=put' - - assert_equal :put, @request.request_method - end - - def test_delete - set_content_data '_method=delete' - - assert_equal :delete, @request.request_method - end -end - class RackRequestNeedsRewoundTest < BaseRackTest def test_body_should_be_rewound data = 'foo' diff --git a/actionpack/test/controller/request_test.rb b/actionpack/test/controller/request_test.rb index c2c35ad6fe..3e10a4665e 100644 --- a/actionpack/test/controller/request_test.rb +++ b/actionpack/test/controller/request_test.rb @@ -303,18 +303,16 @@ def test_invalid_http_method_raises_exception end def test_allow_method_hacking_on_post - self.request_method = :post [:get, :head, :options, :put, :post, :delete].each do |method| - @request.instance_eval { @parameters = { :_method => method.to_s } ; @request_method = nil } + self.request_method = method @request.request_method(true) assert_equal(method == :head ? :get : method, @request.method) end end def test_invalid_method_hacking_on_post_raises_exception - self.request_method = :post - @request.instance_eval { @parameters = { :_method => :random_method } ; @request_method = nil } assert_raises(ActionController::UnknownHttpMethod) do + self.request_method = :_random_method @request.request_method(true) end end -- GitLab