Browse files

Support X-Http-Method-Override header in MethodOverride middleware

  • Loading branch information...
1 parent f7958a8 commit 8b8690bcb7762cde729088c2abdacb610ebea1f7 @josh josh committed Dec 30, 2008
Showing with 18 additions and 2 deletions.
  1. +6 −1 lib/rack/methodoverride.rb
  2. +12 −1 test/spec_rack_methodoverride.rb
@@ -2,14 +2,19 @@ module Rack
class MethodOverride
+ METHOD_OVERRIDE_PARAM_KEY = "_method".freeze
def initialize(app)
@app = app
def call(env)
if env["REQUEST_METHOD"] == "POST"
req =
- method = req.POST["_method"].to_s.upcase
+ method = method.to_s.upcase
if HTTP_METHODS.include?(method)
env["REQUEST_METHOD"] = method
jcrosby Dec 30, 2008 Member

We may want to consider noting in the env somewhere (perhaps with something similar to HTTP Via headers?) that this middleware is in use or at least documenting that it should only be used behind auth middleware. OAuth, for example, uses the request method as part of signature verification and would report an invalid signature in the case of PUT overriding POST.

@@ -13,14 +13,25 @@
req.env["REQUEST_METHOD"].should.equal "GET"
- specify "should modify REQUEST_METHOD for POST requests" do
+ specify "_method parameter should modify REQUEST_METHOD for POST requests" do
env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=put")
app = { |env| })
req =
req.env["REQUEST_METHOD"].should.equal "PUT"
+ specify "X-HTTP-Method-Override header should modify REQUEST_METHOD for POST requests" do
+ env = Rack::MockRequest.env_for("/",
+ :method => "POST",
+ )
+ app = { |env| })
+ req =
+ req.env["REQUEST_METHOD"].should.equal "PUT"
+ end
specify "should not modify REQUEST_METHOD if the method is unknown" do
env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=foo")
app = { |env| })

3 comments on commit 8b8690b

josh commented on 8b8690b Dec 30, 2008

I should not matter. I use this with OpenID and it validates the headers fine since redirects are always GET therefore the request method is never altered.

I suppose it would be a problem if you intentionally tried to use a PUT method with OAuth, but I think thats a rare case because most of the stuff happens over GET.


OpenID solves a different problem than OAuth. Rather than doing authentication with redirects like OpenID, OAuth does authorization. Each request to an API endpoint (GET /foos/123, POST /foos, DELETE /foos/123, etc.) is signed by the user agent using the request method, URL, parameters, a timestamp, and a nonce. OAuth can be used for all HTTP methods and thus needs to know the method used to generate the signature before sending the request. The signature is generated again by a service endpoint and matched against the client’s signature to determine if the request is valid and authorized.

See Section 9.1 of the spec for reference:

Also, see the assembly of a signature base string in action in the appendix, section A.5.1 “Generating Signature Base String.”

It is certainly useful to clean up POST method tunneling hacks as this middleware attempts to do, but there should be a transparent way of determining that this has happened. A pseudo-via-header is one possibility. Another might be storing the original request method in the env somewhere. A third might be storing the adjusted request method under its own env key so that this would be more opt-in and less likely to cause confusion.

dkubb replied Jan 1, 2009

There is related discussion about this commit in chneukirchen/rack:

Please sign in to comment.