From 3aa1f1de602b06d15c5e8d2e2a8fd22c4f652f5c Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Mon, 28 Jan 2019 13:18:37 -0500 Subject: [PATCH] Add support for net-http2 backend --- lib/webmock.rb | 1 + .../http_lib_adapters/net_http2_adapter.rb | 60 +++++++++++++++++++ webmock.gemspec | 1 + 3 files changed, 62 insertions(+) create mode 100644 lib/webmock/http_lib_adapters/net_http2_adapter.rb diff --git a/lib/webmock.rb b/lib/webmock.rb index 8ac085a0d..a812335f2 100644 --- a/lib/webmock.rb +++ b/lib/webmock.rb @@ -46,6 +46,7 @@ require_relative 'webmock/http_lib_adapters/http_lib_adapter_registry' require_relative 'webmock/http_lib_adapters/http_lib_adapter' require_relative 'webmock/http_lib_adapters/net_http' +require_relative 'webmock/http_lib_adapters/net_http2_adapter' require_relative 'webmock/http_lib_adapters/http_rb_adapter' require_relative 'webmock/http_lib_adapters/httpclient_adapter' require_relative 'webmock/http_lib_adapters/patron_adapter' diff --git a/lib/webmock/http_lib_adapters/net_http2_adapter.rb b/lib/webmock/http_lib_adapters/net_http2_adapter.rb new file mode 100644 index 000000000..6e147154f --- /dev/null +++ b/lib/webmock/http_lib_adapters/net_http2_adapter.rb @@ -0,0 +1,60 @@ +require 'net-http2' + +module WebMock + module HttpLibAdapters + class NetHttp2Adapter < HttpLibAdapter + adapter_for :net_http2 + + OriginalClient = NetHttp2::Client unless const_defined?(:OriginalClient) + OriginalStream = NetHttp2::Stream unless const_defined?(:OriginalStream) + + def self.enable! + NetHttp2.send(:remove_const, :Stream) + NetHttp2.send(:remove_const, :Client) + NetHttp2.send(:const_set, :Stream, @webMockNetHTTP2Stream) + NetHttp2.send(:const_set, :Client, @webMockNetHTTP2Client) + end + + def self.disable! + NetHttp2.send(:remove_const, :Stream) + NetHttp2.send(:remove_const, :Client) + NetHttp2.send(:const_set, :Stream, OriginalStream) + NetHttp2.send(:const_set, :Client, OriginalClient) + end + + @webMockNetHTTP2Stream = Class.new(OriginalStream) do + def send_request_data + uri = @request.uri.dup + uri.path = @request.full_path.to_s + sig = WebMock::RequestSignature.new(@request.method, uri.to_s, body: @request.body, headers: @request.headers) + WebMock::RequestRegistry.instance.requested_signatures.put(sig) + + if webmock_response = WebMock::StubRegistry.instance.response_for_request(sig) + WebMock::CallbackRegistry.invoke_callbacks({ lib: :net_http2 }, sig, webmock_response) + return if webmock_response.should_timeout + + if async? + @request.emit(:headers, webmock_response.headers.merge(":status" => webmock_response.status.first.to_s)) + @request.emit(:body_chunk, webmock_response.body) + @request.emit(:close, nil) + else + @headers.merge!((webmock_response.headers || {}).merge(":status" => webmock_response.status.first.to_s)) + @data << webmock_response.body + @completed = true + @mutex.synchronize { @cv.signal } + end + elsif WebMock.net_connect_allowed?(sig.uri) + raise "WebMock NetHTTP2 backend does not support net_connect_allowed yet" + else + raise WebMock::NetConnectNotAllowedError, sig + end + end + end + + @webMockNetHTTP2Client = Class.new(OriginalClient) do + def new_socket + end + end + end + end +end diff --git a/webmock.gemspec b/webmock.gemspec index 494ddf7f0..2167543fe 100644 --- a/webmock.gemspec +++ b/webmock.gemspec @@ -35,6 +35,7 @@ Gem::Specification.new do |s| s.add_development_dependency 'em-http-request', '>= 1.0.2' s.add_development_dependency 'em-synchrony', '>= 1.0.0' s.add_development_dependency 'excon', '>= 0.27.5' + s.add_development_dependency 'net-http2', '>= 0.18.0' s.add_development_dependency 'minitest', '>= 5.0.0' s.add_development_dependency 'test-unit', '>= 3.0.0' s.add_development_dependency 'rdoc', '> 3.5.0'