diff options
Diffstat (limited to 'actionpack')
-rw-r--r-- | actionpack/CHANGELOG | 2 | ||||
-rwxr-xr-x | actionpack/lib/action_controller/base.rb | 2 | ||||
-rwxr-xr-x | actionpack/lib/action_controller/request.rb | 33 | ||||
-rw-r--r-- | actionpack/test/controller/request_test.rb | 19 |
4 files changed, 42 insertions, 14 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index eaefdb77fc..0155731943 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *2.0.0 [RC2]* (November 28th, 2007) +* Raise UnknownHttpMethod exception for unknown HTTP methods. Closes #10303 [tarmo] + * Update to Prototype -r8232. [sam] * Make sure the optimisation code for routes doesn't get used if :host, :anchor or :port are provided in the hash arguments. [pager, Koz] #10292 diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 3193362fc8..b9fd25aa8f 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -85,6 +85,8 @@ module ActionController #:nodoc: end end + class UnknownHttpMethod < ActionControllerError #:nodoc: + end # Action Controllers are the core of a web request in Rails. They are made up of one or more actions that are executed # on request and then either render a template or redirect to another action. An action is defined as a public method diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb index 2926ead13a..2e63180f80 100755 --- a/actionpack/lib/action_controller/request.rb +++ b/actionpack/lib/action_controller/request.rb @@ -3,6 +3,9 @@ require 'stringio' require 'strscan' module ActionController + # HTTP methods which are accepted by default. + ACCEPTED_HTTP_METHODS = Set.new(%w( get head put post delete )) + # CgiRequest and TestRequest provide concrete implementations. class AbstractRequest cattr_accessor :relative_url_root @@ -12,18 +15,24 @@ module ActionController # such as { 'RAILS_ENV' => 'production' }. attr_reader :env + # The true HTTP request method as a lowercase symbol, such as :get. + # UnknownHttpMethod is raised for invalid methods not listed in ACCEPTED_HTTP_METHODS. + def request_method + @request_method ||= begin + method = ((@env['REQUEST_METHOD'] == 'POST' && !parameters[:_method].blank?) ? parameters[:_method].to_s : @env['REQUEST_METHOD']).downcase + if ACCEPTED_HTTP_METHODS.include?(method) + method.to_sym + else + raise UnknownHttpMethod, "#{method}, accepted HTTP methods are #{ACCEPTED_HTTP_METHODS.to_a.to_sentence}" + end + end + end + # The HTTP request method as a lowercase symbol, such as :get. # Note, HEAD is returned as :get since the two are functionally # equivalent from the application's perspective. def method - @request_method ||= - if @env['REQUEST_METHOD'] == 'POST' && !parameters[:_method].blank? - parameters[:_method].to_s.downcase.to_sym - else - @env['REQUEST_METHOD'].downcase.to_sym - end - - @request_method == :head ? :get : @request_method + request_method == :head ? :get : request_method end # Is this a GET (or HEAD) request? Equivalent to request.method == :get @@ -33,23 +42,23 @@ module ActionController # Is this a POST request? Equivalent to request.method == :post def post? - method == :post + request_method == :post end # Is this a PUT request? Equivalent to request.method == :put def put? - method == :put + request_method == :put end # Is this a DELETE request? Equivalent to request.method == :delete def delete? - method == :delete + request_method == :delete end # Is this a HEAD request? request.method sees HEAD as :get, so check the # HTTP method directly. def head? - @env['REQUEST_METHOD'].downcase.to_sym == :head + request_method == :head end def headers diff --git a/actionpack/test/controller/request_test.rb b/actionpack/test/controller/request_test.rb index 1ade378739..1ae1f975a0 100644 --- a/actionpack/test/controller/request_test.rb +++ b/actionpack/test/controller/request_test.rb @@ -306,11 +306,26 @@ class RequestTest < Test::Unit::TestCase end end + def test_invalid_http_method_raises_exception + set_request_method_to :random_method + assert_raises(ActionController::UnknownHttpMethod) do + @request.method + end + end + def test_allow_method_hacking_on_post set_request_method_to :post - [:get, :put, :delete].each do |method| + [:get, :head, :put, :post, :delete].each do |method| @request.instance_eval { @parameters = { :_method => method } ; @request_method = nil } - assert_equal method, @request.method + assert_equal(method == :head ? :get : method, @request.method) + end + end + + def test_invalid_method_hacking_on_post_raises_exception + set_request_method_to :post + @request.instance_eval { @parameters = { :_method => :random_method } ; @request_method = nil } + assert_raises(ActionController::UnknownHttpMethod) do + @request.method end end |