From f49e7a6b4d985276ff10cd80c326f4105259657e Mon Sep 17 00:00:00 2001 From: Steve Hull Date: Thu, 9 Jun 2011 13:58:54 -0700 Subject: [PATCH 1/7] Updating em http request implementation to work with latest version of em-http-request. --- .../http_lib_adapters/em_http_request.rb | 97 ++++++++----------- 1 file changed, 43 insertions(+), 54 deletions(-) diff --git a/lib/webmock/http_lib_adapters/em_http_request.rb b/lib/webmock/http_lib_adapters/em_http_request.rb index e6985e3d9..7ec429a1f 100644 --- a/lib/webmock/http_lib_adapters/em_http_request.rb +++ b/lib/webmock/http_lib_adapters/em_http_request.rb @@ -1,59 +1,48 @@ -if defined?(EventMachine::HttpRequest) +if defined?(EventMachine::HttpClient) module EventMachine - OriginalHttpRequest = HttpRequest unless const_defined?(:OriginalHttpRequest) + OriginalHttpClient = HttpClient unless const_defined?(:OriginalHttpClient) - class WebMockHttpRequest < EventMachine::HttpRequest + class WebMockHttpClient < EventMachine::HttpClient include HttpEncoding - class WebMockHttpClient < EventMachine::HttpClient - - def setup(response, uri, error = nil) - @last_effective_url = @uri = uri - if error - on_error(error) - fail(self) - else - EM.next_tick do - receive_data(response) - succeed(self) - end + def setup(response, uri, error = nil) + @last_effective_url = @uri = uri + if error + on_error(error) + fail(self) + else + EM.next_tick do + @conn.receive_data(response) + succeed(self) end end - - def unbind - end - - def close_connection - end end - def send_request_with_webmock(&block) + def send_request_with_webmock(head, body) request_signature = build_request_signature WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) if WebMock::StubRegistry.instance.registered_request?(request_signature) webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature) - WebMock::CallbackRegistry.invoke_callbacks( - {:lib => :em_http_request}, request_signature, webmock_response) - client = WebMockHttpClient.new(nil) - client.on_error("WebMock timeout error") if webmock_response.should_timeout - client.setup(make_raw_response(webmock_response), @uri, - webmock_response.should_timeout ? "WebMock timeout error" : nil) - client + WebMock::CallbackRegistry.invoke_callbacks({:lib => :em_http_request}, request_signature, webmock_response) + on_error("WebMock timeout error") if webmock_response.should_timeout + setup(make_raw_response(webmock_response), @uri, + webmock_response.should_timeout ? "WebMock timeout error" : nil) + self elsif WebMock.net_connect_allowed?(request_signature.uri) - http = send_request_without_webmock(&block) - http.callback { + send_request_without_webmock(head, body) + @conn.conn.callback { if WebMock::CallbackRegistry.any_callbacks? - webmock_response = build_webmock_response(http) + webmock_response = build_webmock_response(self) WebMock::CallbackRegistry.invoke_callbacks( {:lib => :em_http_request, :real_request => true}, request_signature, webmock_response) end } - http + self else raise WebMock::NetConnectNotAllowedError.new(request_signature) end @@ -74,31 +63,31 @@ def build_webmock_response(http) end def build_request_signature - if @req - options = @req.options - method = @req.method - uri = @req.uri - else - options = @options - method = @method - uri = @uri - end - - if options[:authorization] || options['authorization'] - auth = (options[:authorization] || options['authorization']) + method = @req.method + uri = @req.uri + auth = @req.proxy[:authorization] + query = @req.query + headers = @req.headers + body = @req.body + + if auth userinfo = auth.join(':') userinfo = WebMock::Util::URI.encode_unsafe_chars_in_userinfo(userinfo) - options.reject! {|k,v| k.to_s == 'authorization' } #we added it to url userinfo + if @req + @req.proxy.reject! {|k,v| t.to_s == 'authorization' } + else + options.reject! {|k,v| k.to_s == 'authorization' } #we added it to url userinfo + end uri.userinfo = userinfo end - uri.query = encode_query(@req.uri, options[:query]).slice(/\?(.*)/, 1) + uri.query = encode_query(@req.uri, query).slice(/\?(.*)/, 1) WebMock::RequestSignature.new( method.downcase.to_sym, uri.to_s, - :body => (options[:body] || options['body']), - :headers => (options[:head] || options['head']) + :body => body, + :headers => headers ) end @@ -128,17 +117,17 @@ def make_raw_response(response) end def self.activate! - EventMachine.send(:remove_const, :HttpRequest) - EventMachine.send(:const_set, :HttpRequest, WebMockHttpRequest) + EventMachine.send(:remove_const, :HttpClient) + EventMachine.send(:const_set, :HttpClient, WebMockHttpClient) end def self.deactivate! - EventMachine.send(:remove_const, :HttpRequest) - EventMachine.send(:const_set, :HttpRequest, OriginalHttpRequest) + EventMachine.send(:remove_const, :HttpClient) + EventMachine.send(:const_set, :HttpClient, OriginalHttpClient) end end end - EventMachine::WebMockHttpRequest.activate! + EventMachine::WebMockHttpClient.activate! end From 0d1a4d0cb4e889787d589573b92d311e0a09ed4b Mon Sep 17 00:00:00 2001 From: Steve Hull Date: Thu, 9 Jun 2011 16:08:53 -0700 Subject: [PATCH 2/7] Still working on getting em-http-request support updated (WIP) --- .../http_lib_adapters/em_http_request.rb | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/lib/webmock/http_lib_adapters/em_http_request.rb b/lib/webmock/http_lib_adapters/em_http_request.rb index 7ec429a1f..2b4a15dc3 100644 --- a/lib/webmock/http_lib_adapters/em_http_request.rb +++ b/lib/webmock/http_lib_adapters/em_http_request.rb @@ -3,7 +3,6 @@ module EventMachine OriginalHttpClient = HttpClient unless const_defined?(:OriginalHttpClient) - class WebMockHttpClient < EventMachine::HttpClient include HttpEncoding @@ -13,10 +12,8 @@ def setup(response, uri, error = nil) on_error(error) fail(self) else - EM.next_tick do - @conn.receive_data(response) - succeed(self) - end + @conn.receive_data(response) + succeed(self) end end @@ -29,16 +26,21 @@ def send_request_with_webmock(head, body) webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature) WebMock::CallbackRegistry.invoke_callbacks({:lib => :em_http_request}, request_signature, webmock_response) on_error("WebMock timeout error") if webmock_response.should_timeout + self.response = webmock_response.body + webmock_response.headers.each do |k, v| + self.response_header[k.upcase.gsub('-','_')] = v + end if webmock_response.headers setup(make_raw_response(webmock_response), @uri, webmock_response.should_timeout ? "WebMock timeout error" : nil) self elsif WebMock.net_connect_allowed?(request_signature.uri) send_request_without_webmock(head, body) - @conn.conn.callback { + callback { if WebMock::CallbackRegistry.any_callbacks? - webmock_response = build_webmock_response(self) + webmock_response = build_webmock_response WebMock::CallbackRegistry.invoke_callbacks( - {:lib => :em_http_request, :real_request => true}, request_signature, + {:lib => :em_http_request, :real_request => true}, + request_signature, webmock_response) end } @@ -54,11 +56,11 @@ def send_request_with_webmock(head, body) private - def build_webmock_response(http) + def build_webmock_response webmock_response = WebMock::Response.new - webmock_response.status = [http.response_header.status, http.response_header.http_reason] - webmock_response.headers = http.response_header - webmock_response.body = http.response + webmock_response.status = [response_header.status, response_header.http_reason] + webmock_response.headers = response_header + webmock_response.body = response webmock_response end From ed33a331fde497f3f4f3ec4b20c32b4a6a19c139 Mon Sep 17 00:00:00 2001 From: Steve Hull Date: Thu, 9 Jun 2011 18:45:34 -0700 Subject: [PATCH 3/7] More progress toward updating em-http-request (WIP) --- Gemfile | 1 + .../http_lib_adapters/em_http_request.rb | 11 +++---- spec/em_http_request_spec_helper.rb | 2 ++ spec/webmock_shared.rb | 29 +++++++++++++++---- webmock.gemspec | 2 +- 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/Gemfile b/Gemfile index 7dff8ab94..fbba45f4b 100644 --- a/Gemfile +++ b/Gemfile @@ -5,6 +5,7 @@ gemspec group :development do gem 'guard-rspec' gem 'rb-fsevent' + gem 'ruby-debug19', :require => 'ruby-debug' end platforms :jruby do diff --git a/lib/webmock/http_lib_adapters/em_http_request.rb b/lib/webmock/http_lib_adapters/em_http_request.rb index 2b4a15dc3..5e93b6395 100644 --- a/lib/webmock/http_lib_adapters/em_http_request.rb +++ b/lib/webmock/http_lib_adapters/em_http_request.rb @@ -6,6 +6,10 @@ module EventMachine class WebMockHttpClient < EventMachine::HttpClient include HttpEncoding + def uri + @req.uri + end + def setup(response, uri, error = nil) @last_effective_url = @uri = uri if error @@ -26,10 +30,6 @@ def send_request_with_webmock(head, body) webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature) WebMock::CallbackRegistry.invoke_callbacks({:lib => :em_http_request}, request_signature, webmock_response) on_error("WebMock timeout error") if webmock_response.should_timeout - self.response = webmock_response.body - webmock_response.headers.each do |k, v| - self.response_header[k.upcase.gsub('-','_')] = v - end if webmock_response.headers setup(make_raw_response(webmock_response), @uri, webmock_response.should_timeout ? "WebMock timeout error" : nil) self @@ -98,10 +98,12 @@ def make_raw_response(response) response.raise_error_if_any status, headers, body = response.status, response.headers, response.body + headers ||= {} response_string = [] response_string << "HTTP/1.1 #{status[0]} #{status[1]}" + headers["Content-Length"] = body.length unless headers["Content-Length"] headers.each do |header, value| value = value.join(", ") if value.is_a?(Array) @@ -131,5 +133,4 @@ def self.deactivate! end EventMachine::WebMockHttpClient.activate! - end diff --git a/spec/em_http_request_spec_helper.rb b/spec/em_http_request_spec_helper.rb index e809d9b36..28df29e3b 100644 --- a/spec/em_http_request_spec_helper.rb +++ b/spec/em_http_request_spec_helper.rb @@ -6,6 +6,7 @@ def failed end def http_request(method, uri, options = {}, &block) + @http = nil response = nil error = nil uri = Addressable::URI.heuristic_parse(uri) @@ -34,6 +35,7 @@ def http_request(method, uri, options = {}, &block) }) EventMachine.stop } + @http = http } raise error if error response diff --git a/spec/webmock_shared.rb b/spec/webmock_shared.rb index 89aa94371..04c1c1144 100644 --- a/spec/webmock_shared.rb +++ b/spec/webmock_shared.rb @@ -532,7 +532,11 @@ class MyException < StandardError; end; it "should return declared status message" do stub_http_request(:get, "www.example.com").to_return(:status => [500, "Internal Server Error"]) - http_request(:get, "http://www.example.com/").message.should == "Internal Server Error" + response = http_request(:get, "http://www.example.com/") + # not supported by em-http-request, it always returns "unknown" for http_reason + unless @http.is_a?(EventMachine::WebMockHttpClient) + response.message.should == "Internal Server Error" + end end it "should return default status code" do @@ -542,7 +546,11 @@ class MyException < StandardError; end; it "should return default empty message" do stub_http_request(:get, "www.example.com") - http_request(:get, "http://www.example.com/").message.should == "" + response = http_request(:get, "http://www.example.com/") + # not supported by em-http-request, it always returns "unknown" for http_reason + unless @http.is_a?(EventMachine::WebMockHttpClient) + response.message.should == "" + end end it "should return body declared as IO" do @@ -640,7 +648,10 @@ def call(request) end it "should return recorded status message" do - @response.message.should == "OK" + # not supported by em-http-request, it always returns "unknown" for http_reason + unless @http.is_a?(EventMachine::WebMockHttpClient) + @response.message.should == "OK" + end end it "should ensure file is closed" do @@ -676,7 +687,10 @@ def call(request) end it "should return recorded status message" do - @response.message.should == "OK" + # not supported by em-http-request, it always returns "unknown" for http_reason + unless @http.is_a?(EventMachine::WebMockHttpClient) + @response.message.should == "OK" + end end end @@ -1491,8 +1505,11 @@ def call(request) end it "should pass response with status and message" do - @response.status[0].should == 302 - @response.status[1].should == "Found" + # not supported by em-http-request, it always returns "unknown" for http_reason + unless @http.is_a?(EventMachine::WebMockHttpClient) + @response.status[0].should == 302 + @response.status[1].should == "Found" + end end it "should pass response with headers" do diff --git a/webmock.gemspec b/webmock.gemspec index 9c85a042b..9a41b84e7 100644 --- a/webmock.gemspec +++ b/webmock.gemspec @@ -20,7 +20,7 @@ Gem::Specification.new do |s| s.add_development_dependency 'rspec', '>= 2.0.0' s.add_development_dependency 'httpclient', '>= 2.1.5.2' s.add_development_dependency 'patron', '>= 0.4.9' - s.add_development_dependency 'em-http-request', '>= 0.2.14' + s.add_development_dependency 'em-http-request', '>= 1.0.0.beta.4' s.add_development_dependency 'curb', '>= 0.7.8' s.files = `git ls-files`.split("\n") From 1093577b747e529f5c643b04e26692b4be5559fb Mon Sep 17 00:00:00 2001 From: Steve Hull Date: Fri, 10 Jun 2011 00:00:49 -0700 Subject: [PATCH 4/7] Adding test around 'double resume' exception as well as fix. --- Gemfile | 1 + .../http_lib_adapters/em_http_request.rb | 20 +++++++++++++ spec/em_http_request_spec.rb | 28 +++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/Gemfile b/Gemfile index fbba45f4b..8b86399c9 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,7 @@ group :development do gem 'guard-rspec' gem 'rb-fsevent' gem 'ruby-debug19', :require => 'ruby-debug' + gem 'em-synchrony', '0.3.0.beta.1', :require => false end platforms :jruby do diff --git a/lib/webmock/http_lib_adapters/em_http_request.rb b/lib/webmock/http_lib_adapters/em_http_request.rb index 5e93b6395..2a7d97960 100644 --- a/lib/webmock/http_lib_adapters/em_http_request.rb +++ b/lib/webmock/http_lib_adapters/em_http_request.rb @@ -3,6 +3,26 @@ module EventMachine OriginalHttpClient = HttpClient unless const_defined?(:OriginalHttpClient) + if defined?(Synchrony) + # have to make the callbacks fire on the next tick in order + # to avoid the dreaded "double resume" exception + module HTTPMethods + %w[get head post delete put].each do |type| + class_eval %[ + def #{type}(options = {}, &blk) + f = Fiber.current + + conn = setup_request(:#{type}, options, &blk) + conn.callback { EM.next_tick { f.resume(conn) } } + conn.errback { EM.next_tick { f.resume(conn) } } + + Fiber.yield + end + ] + end + end + end + class WebMockHttpClient < EventMachine::HttpClient include HttpEncoding diff --git a/spec/em_http_request_spec.rb b/spec/em_http_request_spec.rb index e4ff3b461..5abcffee7 100644 --- a/spec/em_http_request_spec.rb +++ b/spec/em_http_request_spec.rb @@ -35,6 +35,34 @@ http_request(:get, "http://www.example.com/?x=3", :query => "a[]=b&a[]=c").body.should == "abc" end + # not pretty, but it works + it "should work with synchrony" do + # need to reload the webmock em-http adapter after we require synchrony + webmock_em_http = File.expand_path(File.join(File.dirname(__FILE__), "../lib/webmock/http_lib_adapters/em_http_request.rb")) + $".delete webmock_em_http + EM::WebMockHttpClient.deactivate! + require 'em-synchrony' + require 'em-synchrony/em-http' + require webmock_em_http + stub_request(:post, /.*.testserver.com*/).to_return(:status => 200, :body => 'ok') + lambda { + EM.run do + fiber = Fiber.new do + http = EM::HttpRequest.new("http://www.testserver.com").post :body => "foo=bar&baz=bang", :timeout => 60 + EM.stop + end + fiber.resume + end + }.should_not raise_error + module ::EM::HTTPMethods + alias :put :aput + alias :get :aget + alias :head :ahead + alias :post :apost + alias :delet :adelete + end + end + describe "mocking EM::HttpClient API" do before { stub_http_request(:get, "www.example.com/") } subject do From 10fa0a24a652133aaebbccc7e53a1843d3603479 Mon Sep 17 00:00:00 2001 From: Steve Hull Date: Tue, 14 Jun 2011 16:18:28 -0700 Subject: [PATCH 5/7] Specs are green, everything working. Also blocking EM from connecting to the remote server (unlike before) --- .../http_lib_adapters/em_http_request.rb | 45 +++++++++++++-- spec/em_http_request_spec.rb | 55 +++++++++++-------- spec/em_http_request_spec_helper.rb | 9 +-- 3 files changed, 77 insertions(+), 32 deletions(-) diff --git a/lib/webmock/http_lib_adapters/em_http_request.rb b/lib/webmock/http_lib_adapters/em_http_request.rb index 2a7d97960..d9aad3cc2 100644 --- a/lib/webmock/http_lib_adapters/em_http_request.rb +++ b/lib/webmock/http_lib_adapters/em_http_request.rb @@ -2,6 +2,7 @@ module EventMachine OriginalHttpClient = HttpClient unless const_defined?(:OriginalHttpClient) + OriginalHttpConnection = HttpConnection unless const_defined?(:OriginalHttpConnection) if defined?(Synchrony) # have to make the callbacks fire on the next tick in order @@ -23,6 +24,33 @@ def #{type}(options = {}, &blk) end end + class WebMockHttpConnection < HttpConnection + def webmock_activate_connection(client) + request_signature = client.request_signature + + if WebMock::StubRegistry.instance.registered_request?(request_signature) + conn = HttpStubConnection.new rand(10000) + post_init + + @deferred = false + @conn = conn + + conn.parent = self + conn.pending_connect_timeout = @connopts.connect_timeout + conn.comm_inactivity_timeout = @connopts.inactivity_timeout + + finalize_request(client) + @conn.set_deferred_status :succeeded + elsif WebMock.net_connect_allowed?(request_signature.uri) + real_activate_connection(client) + else + raise WebMock::NetConnectNotAllowedError.new(request_signature) + end + end + alias_method :real_activate_connection, :activate_connection + alias_method :activate_connection, :webmock_activate_connection + end + class WebMockHttpClient < EventMachine::HttpClient include HttpEncoding @@ -42,16 +70,16 @@ def setup(response, uri, error = nil) end def send_request_with_webmock(head, body) - request_signature = build_request_signature - WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) if WebMock::StubRegistry.instance.registered_request?(request_signature) webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature) - WebMock::CallbackRegistry.invoke_callbacks({:lib => :em_http_request}, request_signature, webmock_response) on_error("WebMock timeout error") if webmock_response.should_timeout - setup(make_raw_response(webmock_response), @uri, - webmock_response.should_timeout ? "WebMock timeout error" : nil) + WebMock::CallbackRegistry.invoke_callbacks({:lib => :em_http_request}, request_signature, webmock_response) + EM.next_tick { + setup(make_raw_response(webmock_response), @uri, + webmock_response.should_timeout ? "WebMock timeout error" : nil) + } self elsif WebMock.net_connect_allowed?(request_signature.uri) send_request_without_webmock(head, body) @@ -73,6 +101,9 @@ def send_request_with_webmock(head, body) alias_method :send_request_without_webmock, :send_request alias_method :send_request, :send_request_with_webmock + def request_signature + @request_signature ||= build_request_signature + end private @@ -141,11 +172,15 @@ def make_raw_response(response) end def self.activate! + EventMachine.send(:remove_const, :HttpConnection) + EventMachine.send(:const_set, :HttpConnection, WebMockHttpConnection) EventMachine.send(:remove_const, :HttpClient) EventMachine.send(:const_set, :HttpClient, WebMockHttpClient) end def self.deactivate! + EventMachine.send(:remove_const, :HttpConnection) + EventMachine.send(:const_set, :HttpConnection, OriginalHttpConnection) EventMachine.send(:remove_const, :HttpClient) EventMachine.send(:const_set, :HttpClient, OriginalHttpClient) end diff --git a/spec/em_http_request_spec.rb b/spec/em_http_request_spec.rb index 5abcffee7..e5a4af198 100644 --- a/spec/em_http_request_spec.rb +++ b/spec/em_http_request_spec.rb @@ -36,30 +36,39 @@ end # not pretty, but it works - it "should work with synchrony" do - # need to reload the webmock em-http adapter after we require synchrony - webmock_em_http = File.expand_path(File.join(File.dirname(__FILE__), "../lib/webmock/http_lib_adapters/em_http_request.rb")) - $".delete webmock_em_http - EM::WebMockHttpClient.deactivate! - require 'em-synchrony' - require 'em-synchrony/em-http' - require webmock_em_http - stub_request(:post, /.*.testserver.com*/).to_return(:status => 200, :body => 'ok') - lambda { - EM.run do - fiber = Fiber.new do - http = EM::HttpRequest.new("http://www.testserver.com").post :body => "foo=bar&baz=bang", :timeout => 60 - EM.stop + describe "with synchrony" do + let(:webmock_em_http) { File.expand_path(File.join(File.dirname(__FILE__), "../lib/webmock/http_lib_adapters/em_http_request.rb")) } + + before(:each) do + # need to reload the webmock em-http adapter after we require synchrony + EM::WebMockHttpClient.deactivate! + $".delete webmock_em_http + require 'em-synchrony' + require 'em-synchrony/em-http' + require webmock_em_http + end + + it "should work" do + stub_request(:post, /.*.testserver.com*/).to_return(:status => 200, :body => 'ok') + lambda { + EM.run do + fiber = Fiber.new do + http = EM::HttpRequest.new("http://www.testserver.com").post :body => "foo=bar&baz=bang", :timeout => 60 + EM.stop + end + fiber.resume end - fiber.resume - end - }.should_not raise_error - module ::EM::HTTPMethods - alias :put :aput - alias :get :aget - alias :head :ahead - alias :post :apost - alias :delet :adelete + }.should_not raise_error + end + + after(:each) do + EM.send(:remove_const, :Synchrony) + EM.send(:remove_const, :HTTPMethods) + EM::WebMockHttpClient.deactivate! + $".reject! {|path| path.include? "em-http-request"} + $".delete webmock_em_http + require 'em-http-request' + require webmock_em_http end end diff --git a/spec/em_http_request_spec_helper.rb b/spec/em_http_request_spec_helper.rb index 28df29e3b..8a9468381 100644 --- a/spec/em_http_request_spec_helper.rb +++ b/spec/em_http_request_spec_helper.rb @@ -7,17 +7,18 @@ def failed def http_request(method, uri, options = {}, &block) @http = nil + head = options[:headers] || {} response = nil error = nil uri = Addressable::URI.heuristic_parse(uri) EventMachine.run { - request = EventMachine::HttpRequest.new("#{uri.omit(:userinfo).normalize.to_s}") - http = request.send(:setup_request, method, { + request = EventMachine::HttpRequest.new("#{uri.normalize.to_s}") + http = request.send(method, { :timeout => 10, :body => options[:body], :query => options[:query], - 'authorization' => [uri.user, uri.password], - :head => options[:headers]}, &block) + :head => head.merge('authorization' => [uri.user, uri.password]) + }, &block) http.errback { error = if http.respond_to?(:errors) http.errors From fd1676faed30a19c81c8c39a5e5a6321d945401b Mon Sep 17 00:00:00 2001 From: Steve Hull Date: Tue, 21 Jun 2011 14:28:03 -0700 Subject: [PATCH 6/7] Removing ruby-debug from dev dependencies --- Gemfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Gemfile b/Gemfile index 8b86399c9..7b9fd9fbb 100644 --- a/Gemfile +++ b/Gemfile @@ -5,7 +5,6 @@ gemspec group :development do gem 'guard-rspec' gem 'rb-fsevent' - gem 'ruby-debug19', :require => 'ruby-debug' gem 'em-synchrony', '0.3.0.beta.1', :require => false end From 452796251e3160eb811b7a9ab8f03f09271a4ba0 Mon Sep 17 00:00:00 2001 From: Steve Hull Date: Wed, 6 Jul 2011 00:12:25 -0700 Subject: [PATCH 7/7] em-http-request: supporting request & response middlewares (compliments of phiggins) --- .../http_lib_adapters/em_http_request.rb | 9 ++-- spec/em_http_request_spec.rb | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/lib/webmock/http_lib_adapters/em_http_request.rb b/lib/webmock/http_lib_adapters/em_http_request.rb index d9aad3cc2..1fa975ae3 100644 --- a/lib/webmock/http_lib_adapters/em_http_request.rb +++ b/lib/webmock/http_lib_adapters/em_http_request.rb @@ -116,12 +116,16 @@ def build_webmock_response end def build_request_signature + headers, body = @req.headers, @req.body + + @conn.middleware.select {|m| m.respond_to?(:request) }.each do |m| + headers, body = m.request(self, headers, body) + end + method = @req.method uri = @req.uri auth = @req.proxy[:authorization] query = @req.query - headers = @req.headers - body = @req.body if auth userinfo = auth.join(':') @@ -144,7 +148,6 @@ def build_request_signature ) end - def make_raw_response(response) response.raise_error_if_any diff --git a/spec/em_http_request_spec.rb b/spec/em_http_request_spec.rb index e5a4af198..c74f60658 100644 --- a/spec/em_http_request_spec.rb +++ b/spec/em_http_request_spec.rb @@ -10,6 +10,52 @@ it_should_behave_like "WebMock" + it "should work with request middleware" do + stub_http_request(:get, "www.example.com").with(:body => 'bar') + + middleware = Class.new do + def request(client, head, body) + [{}, 'bar'] + end + end + + EM.run do + conn = EventMachine::HttpRequest.new('http://www.example.com/') + + conn.use middleware + + http = conn.get(:body => 'foo') + + http.callback do + WebMock.should have_requested(:get, "www.example.com").with(:body => 'bar') + EM.stop + end + end + end + + it "should work with response middleware" do + stub_http_request(:get, "www.example.com").to_return(:body => 'foo') + + middleware = Class.new do + def response(resp) + resp.response = 'bar' + end + end + + EM.run do + conn = EventMachine::HttpRequest.new('http://www.example.com/') + + conn.use middleware + + http = conn.get + + http.callback do + http.response.should be == 'bar' + EM.stop + end + end + end + it "should work with streaming" do stub_http_request(:get, "www.example.com").to_return(:body => "abc") response = ""