From 6d05f31b52b3d8503cd9e90b0fe6b335c5757436 Mon Sep 17 00:00:00 2001 From: AkitaOnRails Date: Mon, 24 May 2010 04:10:05 -0300 Subject: [PATCH 1/2] Adding support for the PATCH Verb as it was already approved (http://www.innoq.com/blog/st/2010/03/rfc_5789_patch_method_for_http.html) --- lib/rack/mock.rb | 5 +++-- lib/rack/request.rb | 1 + rack.gemspec | 2 +- test/spec_rack_auth_digest.rb | 8 ++++++++ test/spec_rack_mock.rb | 4 ++++ 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/rack/mock.rb b/lib/rack/mock.rb index e8bc8e4..30ed8ae 100644 --- a/lib/rack/mock.rb +++ b/lib/rack/mock.rb @@ -9,12 +9,12 @@ module Rack # Rack::MockRequest helps testing your Rack application without # actually using HTTP. # - # After performing a request on a URL with get/post/put/delete, it + # After performing a request on a URL with get/post/put/patch/delete, it # returns a MockResponse with useful helper methods for effective # testing. # # You can pass a hash with additional configuration to the - # get/post/put/delete. + # get/post/put/patch/delete. # :input:: A String or IO-like to be used as rack.input. # :fatal:: Raise a FatalWarning if the app writes to rack.errors. # :lint:: If true, wrap the application in a Rack::Lint. @@ -56,6 +56,7 @@ module Rack def get(uri, opts={}) request("GET", uri, opts) end def post(uri, opts={}) request("POST", uri, opts) end def put(uri, opts={}) request("PUT", uri, opts) end + def patch(uri, opts={}) request("PATCH", uri, opts) end def delete(uri, opts={}) request("DELETE", uri, opts) end def request(method="GET", uri="", opts={}) diff --git a/lib/rack/request.rb b/lib/rack/request.rb index b3de1ce..50ffef5 100644 --- a/lib/rack/request.rb +++ b/lib/rack/request.rb @@ -83,6 +83,7 @@ module Rack def get?; request_method == "GET" end def post?; request_method == "POST" end def put?; request_method == "PUT" end + def patch?; request_method == "PATCH" end def delete?; request_method == "DELETE" end def head?; request_method == "HEAD" end diff --git a/rack.gemspec b/rack.gemspec index 52d6431..9923c9e 100644 --- a/rack.gemspec +++ b/rack.gemspec @@ -20,7 +20,7 @@ EOF s.executables << 'rackup' s.require_path = 'lib' s.has_rdoc = true - s.extra_rdoc_files = ['README', 'SPEC', 'KNOWN-ISSUES'] + s.extra_rdoc_files = ['README', 'KNOWN-ISSUES'] s.test_files = Dir['test/{test,spec}_*.rb'] s.author = 'Christian Neukirchen' diff --git a/test/spec_rack_auth_digest.rb b/test/spec_rack_auth_digest.rb index a980acc..6a5ec7e 100644 --- a/test/spec_rack_auth_digest.rb +++ b/test/spec_rack_auth_digest.rb @@ -219,6 +219,14 @@ context 'Rack::Auth::Digest::MD5' do end end + specify 'should return application output if correct credentials given for PATCH (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=patch" do |response| + response.status.should.equal 200 + response.body.to_s.should.equal 'Hi Alice' + end + end + specify 'realm as optional constructor arg' do app = Rack::Auth::Digest::MD5.new(unprotected_app, realm) { true } assert_equal realm, app.realm diff --git a/test/spec_rack_mock.rb b/test/spec_rack_mock.rb index ca52398..3d90d61 100644 --- a/test/spec_rack_mock.rb +++ b/test/spec_rack_mock.rb @@ -56,6 +56,10 @@ context "Rack::MockRequest" do env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "PUT" + res = Rack::MockRequest.new(app).patch("", :input => "foo") + env = YAML.load(res.body) + env["REQUEST_METHOD"].should.equal "PATCH" + res = Rack::MockRequest.new(app).delete("", :input => "foo") env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "DELETE" -- 1.7.0 From fd172fb60683007353a7e506911aecabfdafe2e1 Mon Sep 17 00:00:00 2001 From: AkitaOnRails Date: Mon, 24 May 2010 16:40:18 -0300 Subject: [PATCH 2/2] Adding PATCH support in a few missing places --- lib/rack/methodoverride.rb | 2 +- test/spec_rack_methodoverride.rb | 19 +++++++++++++++++++ test/spec_rack_mock.rb | 2 +- test/spec_rack_request.rb | 10 ++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/rack/methodoverride.rb b/lib/rack/methodoverride.rb index 0eed29f..ddc31f0 100644 --- a/lib/rack/methodoverride.rb +++ b/lib/rack/methodoverride.rb @@ -1,6 +1,6 @@ module Rack class MethodOverride - HTTP_METHODS = %w(GET HEAD PUT POST DELETE OPTIONS) + HTTP_METHODS = %w(GET HEAD PUT PATCH POST DELETE OPTIONS) METHOD_OVERRIDE_PARAM_KEY = "_method".freeze HTTP_METHOD_OVERRIDE_HEADER = "HTTP_X_HTTP_METHOD_OVERRIDE".freeze diff --git a/test/spec_rack_methodoverride.rb b/test/spec_rack_methodoverride.rb index 5745239..e5672a0 100644 --- a/test/spec_rack_methodoverride.rb +++ b/test/spec_rack_methodoverride.rb @@ -32,6 +32,25 @@ context "Rack::MethodOverride" do req.env["REQUEST_METHOD"].should.equal "PUT" end + specify "_method parameter should modify REQUEST_METHOD for PATCH requests" do + env = Rack::MockRequest.env_for("/", :method => "PATCH", :input => "_method=patch") + app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) }) + req = app.call(env) + + req.env["REQUEST_METHOD"].should.equal "PATCH" + end + + specify "X-HTTP-Method-Override header should modify REQUEST_METHOD for PATCH requests" do + env = Rack::MockRequest.env_for("/", + :method => "POST", + "HTTP_X_HTTP_METHOD_OVERRIDE" => "PATCH" + ) + app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) }) + req = app.call(env) + + req.env["REQUEST_METHOD"].should.equal "PATCH" + end + specify "should not modify REQUEST_METHOD if the method is unknown" do env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=foo") app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) }) diff --git a/test/spec_rack_mock.rb b/test/spec_rack_mock.rb index 3d90d61..08997bc 100644 --- a/test/spec_rack_mock.rb +++ b/test/spec_rack_mock.rb @@ -43,7 +43,7 @@ context "Rack::MockRequest" do env["mock.postdata"].should.be.empty end - specify "should allow GET/POST/PUT/DELETE" do + specify "should allow GET/POST/PUT/PATCH/DELETE" do res = Rack::MockRequest.new(app).get("", :input => "foo") env = YAML.load(res.body) env["REQUEST_METHOD"].should.equal "GET" diff --git a/test/spec_rack_request.rb b/test/spec_rack_request.rb index 43a4b87..46a9d7f 100644 --- a/test/spec_rack_request.rb +++ b/test/spec_rack_request.rb @@ -116,6 +116,16 @@ context "Rack::Request" do req.body.read.should.equal "foo=bar&quux=bla" end + specify "can parse POST data on PATCH when media type is form-data" do + req = Rack::Request.new \ + Rack::MockRequest.env_for("/?foo=quux", + "REQUEST_METHOD" => 'PATCH', + "CONTENT_TYPE" => 'application/x-www-form-urlencoded', + :input => "foo=bar&quux=bla") + req.POST.should.equal "foo" => "bar", "quux" => "bla" + req.body.read.should.equal "foo=bar&quux=bla" + end + specify "rewinds input after parsing POST data" do input = StringIO.new("foo=bar&quux=bla") req = Rack::Request.new \ -- 1.7.0