summary refs log tree commit
diff options
context:
space:
mode:
authorS. Brent Faulkner <brentf@unwwwired.net>2009-02-04 23:38:32 -0500
committerRyan Tomayko <rtomayko@gmail.com>2009-02-25 09:10:09 -0800
commita2b8481d7ed33d882fe1850713aa9059f4bfe1fb (patch)
tree58e411f18fd09fd086e34665063a7741679f0186
parent65fe834bca9899d97d43201c294096c2bf3d257a (diff)
downloadrack-a2b8481d7ed33d882fe1850713aa9059f4bfe1fb.tar.gz
Make MethodOverride + Auth::Digest play well together
Auth::Digest::Request#method now uses any value in
rack.methodoverride.original_method to override the value in
REQUEST_METHOD

Signed-off-by: Ryan Tomayko <rtomayko@gmail.com>
-rw-r--r--lib/rack/auth/digest/request.rb2
-rw-r--r--test/spec_rack_auth_digest.rb100
2 files changed, 63 insertions, 39 deletions
diff --git a/lib/rack/auth/digest/request.rb b/lib/rack/auth/digest/request.rb
index a40f57b7..a8aa3bf9 100644
--- a/lib/rack/auth/digest/request.rb
+++ b/lib/rack/auth/digest/request.rb
@@ -8,7 +8,7 @@ module Rack
       class Request < Auth::AbstractRequest
 
         def method
-          @env['REQUEST_METHOD']
+          @env['rack.methodoverride.original_method'] || @env['REQUEST_METHOD']
         end
 
         def digest?
diff --git a/test/spec_rack_auth_digest.rb b/test/spec_rack_auth_digest.rb
index b5b5afc4..34c7e7b4 100644
--- a/test/spec_rack_auth_digest.rb
+++ b/test/spec_rack_auth_digest.rb
@@ -14,7 +14,7 @@ context 'Rack::Auth::Digest::MD5' do
       [ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}"] ]
     end
   end
-  
+
   def protected_app
     app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username|
       { 'Alice' => 'correct-password' }[username]
@@ -23,7 +23,7 @@ context 'Rack::Auth::Digest::MD5' do
     app.opaque = 'this-should-be-secret'
     app
   end
-  
+
   def protected_app_with_hashed_passwords
     app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username|
       username == 'Alice' ? Digest::MD5.hexdigest("Alice:#{realm}:correct-password") : nil
@@ -40,17 +40,21 @@ context 'Rack::Auth::Digest::MD5' do
       '/protected' => protected_app
     })
   end
-  
+
+  def protected_app_with_method_override
+    Rack::MethodOverride.new(protected_app)
+  end
+
   setup do
     @request = Rack::MockRequest.new(protected_app)
   end
 
-  def request(path, headers = {}, &block)
-    response = @request.get(path, headers)
+  def request(method, path, headers = {}, &block)
+    response = @request.request(method, path, headers)
     block.call(response) if block
     return response
   end
-  
+
   class MockDigestRequest
     def initialize(params)
       @params = params
@@ -62,22 +66,25 @@ context 'Rack::Auth::Digest::MD5' do
       super
     end
     def method
-      'GET'
+      @params['method']
     end
     def response(password)
       Rack::Auth::Digest::MD5.new(nil).send :digest, self, password
     end
   end
-  
-  def request_with_digest_auth(path, username, password, options = {}, &block)
-    response = request(path)
-    
+
+  def request_with_digest_auth(method, path, username, password, options = {}, &block)
+    request_options = {}
+    request_options[:input] = options.delete(:input) if options.include? :input
+
+    response = request(method, path, request_options)
+
     return response unless response.status == 401
-    
+
     if wait = options.delete(:wait)
       sleep wait
     end
-    
+
     challenge = response['WWW-Authenticate'].split(' ', 2).last
 
     params = Rack::Auth::Digest::Params.parse(challenge)
@@ -86,12 +93,14 @@ context 'Rack::Auth::Digest::MD5' do
     params['nc'] = '00000001'
     params['cnonce'] = 'nonsensenonce'
     params['uri'] = path
-        
+
+    params['method'] = method
+
     params.update options
-    
+
     params['response'] = MockDigestRequest.new(params).response(password)
-    
-    request(path, { 'HTTP_AUTHORIZATION' => "Digest #{params}" }, &block)
+
+    request(method, path, request_options.merge('HTTP_AUTHORIZATION' => "Digest #{params}"), &block)
   end
 
   def assert_digest_auth_challenge(response)
@@ -101,7 +110,7 @@ context 'Rack::Auth::Digest::MD5' do
     response.headers['WWW-Authenticate'].should =~ /^Digest /
     response.body.should.be.empty
   end
-  
+
   def assert_bad_request(response)
     response.should.be.a.client_error
     response.status.should.equal 400
@@ -109,44 +118,44 @@ context 'Rack::Auth::Digest::MD5' do
   end
 
   specify 'should challenge when no credentials are specified' do
-    request '/' do |response|
+    request 'GET', '/' do |response|
       assert_digest_auth_challenge response
     end
   end
-  
+
   specify 'should return application output if correct credentials given' do
-    request_with_digest_auth '/', 'Alice', 'correct-password' do |response|
+    request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response|
       response.status.should.equal 200
       response.body.to_s.should.equal 'Hi Alice'
     end
-  end  
+  end
 
   specify 'should return application output if correct credentials given (hashed passwords)' do
     @request = Rack::MockRequest.new(protected_app_with_hashed_passwords)
-    
-    request_with_digest_auth '/', 'Alice', 'correct-password' do |response|
+
+    request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response|
       response.status.should.equal 200
       response.body.to_s.should.equal 'Hi Alice'
     end
-  end  
-  
+  end
+
   specify 'should rechallenge if incorrect username given' do
-    request_with_digest_auth '/', 'Bob', 'correct-password' do |response|
+    request_with_digest_auth 'GET', '/', 'Bob', 'correct-password' do |response|
       assert_digest_auth_challenge response
     end
   end
-  
+
   specify 'should rechallenge if incorrect password given' do
-    request_with_digest_auth '/', 'Alice', 'wrong-password' do |response|
+    request_with_digest_auth 'GET', '/', 'Alice', 'wrong-password' do |response|
       assert_digest_auth_challenge response
     end
   end
-  
+
   specify 'should rechallenge with stale parameter if nonce is stale' do
     begin
       Rack::Auth::Digest::Nonce.time_limit = 1
-    
-      request_with_digest_auth '/', 'Alice', 'correct-password', :wait => 2 do |response|
+
+      request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', :wait => 2 do |response|
         assert_digest_auth_challenge response
         response.headers['WWW-Authenticate'].should =~ /\bstale=true\b/
       end
@@ -156,40 +165,55 @@ context 'Rack::Auth::Digest::MD5' do
   end
 
   specify 'should return 400 Bad Request if incorrect qop given' do
-    request_with_digest_auth '/', 'Alice', 'correct-password', 'qop' => 'auth-int' do |response|
+    request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'qop' => 'auth-int' do |response|
       assert_bad_request response
     end
   end
 
   specify 'should return 400 Bad Request if incorrect uri given' do
-    request_with_digest_auth '/', 'Alice', 'correct-password', 'uri' => '/foo' do |response|
+    request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'uri' => '/foo' do |response|
       assert_bad_request response
     end
   end
 
   specify 'should return 400 Bad Request if different auth scheme used' do
-    request '/', 'HTTP_AUTHORIZATION' => 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==' do |response|
+    request 'GET', '/', 'HTTP_AUTHORIZATION' => 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==' do |response|
       assert_bad_request response
     end
   end
 
   specify 'should not require credentials for unprotected path' do
     @request = Rack::MockRequest.new(partially_protected_app)
-    request '/' do |response|
+    request 'GET', '/' do |response|
       response.should.be.ok
     end
   end
 
   specify 'should challenge when no credentials are specified for protected path' do
     @request = Rack::MockRequest.new(partially_protected_app)
-    request '/protected' do |response|
+    request 'GET', '/protected' do |response|
       assert_digest_auth_challenge response
     end
   end
 
   specify 'should return application output if correct credentials given for protected path' do
     @request = Rack::MockRequest.new(partially_protected_app)
-    request_with_digest_auth '/protected', 'Alice', 'correct-password' do |response|
+    request_with_digest_auth 'GET', '/protected', 'Alice', 'correct-password' do |response|
+      response.status.should.equal 200
+      response.body.to_s.should.equal 'Hi Alice'
+    end
+  end
+
+  specify 'should return application output if correct credentials given for POST' do
+    request_with_digest_auth 'POST', '/', 'Alice', 'correct-password' do |response|
+      response.status.should.equal 200
+      response.body.to_s.should.equal 'Hi Alice'
+    end
+  end
+
+  specify 'should return application output if correct credentials given for PUT (using method override of POST)' do
+    @request = Rack::MockRequest.new(protected_app_with_method_override)
+    request_with_digest_auth 'POST', '/', 'Alice', 'correct-password', :input => "_method=put" do |response|
       response.status.should.equal 200
       response.body.to_s.should.equal 'Hi Alice'
     end