Permalink
Browse files

Made HTTP method override proc-based and pluggable. [#364]

Changed the check for specific params to procs that execute
in the request scope, allowing checks for method overrides to
be based on params, headers -- or pretty much anything in the
request. Also changed the name of the array that stores these
checks from browser_method_workarounds to the more accurate
and descriptive http_method_overrides.

Signed-off-by: Michael D. Ivey <ivey@gweezlebur.com>
 (I changed this to yield the controller to the block, instead of
  using instance_eval, as it seemed cleaner and was significantly
  faster.  See benchmark attachment on ticket #364 --ivey)

[#364 state:resolved]
  • Loading branch information...
1 parent 75f7102 commit e7792452a120cdc582b7a1cd826e47eded459d3d @mde mde committed with ivey Jun 9, 2008
Showing with 19 additions and 20 deletions.
  1. +5 −1 lib/merb-core/bootloader.rb
  2. +14 −19 lib/merb-core/dispatch/request.rb
@@ -165,7 +165,11 @@ def run
# Setup some useful defaults
class Merb::BootLoader::Defaults < Merb::BootLoader
def self.run
- Merb::Request.browser_method_workarounds << "_method"
+ Merb::Request.http_method_overrides.concat([
+ proc { |c| c.params[:_method] },
+ proc { |c| c.params[:fb_sig_request_method] },
+ proc { |c| c.env['HTTP_X_HTTP_METHOD_OVERRIDE'] }
+ ])
end
end
@@ -14,12 +14,14 @@ class Request
self.parse_json_params = true
self.parse_xml_params = true
- # Most web browsers can't send PUT or DELETE requests
- # Any Strings stored in this array will be used as paramaters
- # to find the real method. Common examples are _method and
- # fb_sig_request_method
- cattr_accessor :browser_method_workarounds
- self.browser_method_workarounds = []
+ # Flash, and some older browsers can't use arbitrary
+ # request methods -- i.e., are limited to GET/POST.
+ # These user-agents can make POST requests in combination
+ # with these overrides to participate fully in REST
+ # Common examples are _method or fb_sig_request_method
+ # in the params, or an X-HTTP-Method-Override header
+ cattr_accessor :http_method_overrides
+ self.http_method_overrides = []
# Initial the request object.
#
@@ -38,27 +40,20 @@ def initialize(rack_env)
# Symbol:: The name of the request method, e.g. :get.
#
# ==== Notes
- # If the method is post, then the params specified in
- # browser_method_workarounds will be checked for the masquerading method.
- # The first matching workaround wins.
+ # If the method is post, then the blocks specified in
+ # http_method_overrides will be checked for the masquerading method.
+ # The block will get the controller yielded to it. The first matching workaround wins.
+ # To disable this behavior, set http_method_overrides = []
def method
@method ||= begin
request_method = @env['REQUEST_METHOD'].downcase.to_sym
case request_method
when :get, :head, :put, :delete
request_method
when :post
- if self.class.parse_multipart_params
- p = body_and_query_params.merge(multipart_params)
- else
- p = body_and_query_params
- end
m = nil
- self.class.browser_method_workarounds.each do |workaround|
- if p.include?(workaround.to_s)
- m = p[workaround.to_s]
- break
- end
+ self.class.http_method_overrides.each do |o|
+ m ||= o.call(self); break if m
end
m.downcase! if m
METHODS.include?(m) ? m.to_sym : :post

0 comments on commit e779245

Please sign in to comment.