webmock 1.6.4 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gemtest +0 -0
- data/.gitignore +3 -1
- data/.travis.yml +6 -0
- data/CHANGELOG.md +211 -118
- data/Gemfile +16 -1
- data/Guardfile +24 -0
- data/LICENSE +1 -1
- data/README.md +64 -15
- data/Rakefile +19 -6
- data/lib/webmock.rb +9 -4
- data/lib/webmock/api.rb +5 -4
- data/lib/webmock/assertion_failure.rb +1 -1
- data/lib/webmock/callback_registry.rb +1 -1
- data/lib/webmock/config.rb +2 -2
- data/lib/webmock/cucumber.rb +1 -1
- data/lib/webmock/errors.rb +17 -5
- data/lib/webmock/http_lib_adapters/{curb.rb → curb_adapter.rb} +79 -49
- data/lib/webmock/http_lib_adapters/{em_http_request.rb → em_http_request/em_http_request_0_x.rb} +20 -15
- data/lib/webmock/http_lib_adapters/em_http_request/em_http_request_1_x.rb +201 -0
- data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +11 -0
- data/lib/webmock/http_lib_adapters/http_lib_adapter.rb +7 -0
- data/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +19 -0
- data/lib/webmock/http_lib_adapters/{httpclient.rb → httpclient_adapter.rb} +35 -8
- data/lib/webmock/http_lib_adapters/net_http.rb +84 -25
- data/lib/webmock/http_lib_adapters/net_http_response.rb +17 -17
- data/lib/webmock/http_lib_adapters/patron_adapter.rb +124 -0
- data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +166 -0
- data/lib/webmock/minitest.rb +15 -0
- data/lib/webmock/rack_response.rb +52 -0
- data/lib/webmock/request_pattern.rb +4 -2
- data/lib/webmock/request_signature.rb +4 -0
- data/lib/webmock/request_stub.rb +35 -2
- data/lib/webmock/responses_sequence.rb +2 -2
- data/lib/webmock/rspec.rb +2 -2
- data/lib/webmock/rspec/matchers.rb +9 -4
- data/lib/webmock/rspec/matchers/webmock_matcher.rb +1 -1
- data/lib/webmock/stub_registry.rb +1 -1
- data/lib/webmock/stub_request_snippet.rb +14 -11
- data/lib/webmock/util/hash_keys_stringifier.rb +4 -4
- data/lib/webmock/util/headers.rb +3 -3
- data/lib/webmock/util/json.rb +54 -0
- data/lib/webmock/util/uri.rb +1 -1
- data/lib/webmock/version.rb +1 -1
- data/lib/webmock/webmock.rb +20 -3
- data/minitest/test_helper.rb +29 -0
- data/minitest/test_webmock.rb +6 -0
- data/minitest/webmock_spec.rb +30 -0
- data/spec/curb_spec.rb +26 -8
- data/spec/curb_spec_helper.rb +6 -6
- data/spec/em_http_request_spec.rb +95 -1
- data/spec/em_http_request_spec_helper.rb +16 -16
- data/spec/errors_spec.rb +19 -4
- data/spec/example_curl_output.txt +22 -22
- data/spec/http_lib_adapters/http_lib_adapter_registry_spec.rb +17 -0
- data/spec/http_lib_adapters/http_lib_adapter_spec.rb +12 -0
- data/spec/httpclient_spec.rb +1 -1
- data/spec/httpclient_spec_helper.rb +3 -38
- data/spec/my_rack_app.rb +18 -0
- data/spec/net_http_shared.rb +125 -0
- data/spec/net_http_spec.rb +27 -31
- data/spec/net_http_spec_helper.rb +4 -34
- data/spec/network_connection.rb +1 -1
- data/spec/patron_spec_helper.rb +4 -7
- data/spec/quality_spec.rb +60 -0
- data/spec/rack_response_spec.rb +33 -0
- data/spec/real_net_http_spec.rb +20 -0
- data/spec/request_execution_verifier_spec.rb +8 -8
- data/spec/request_pattern_spec.rb +3 -3
- data/spec/request_stub_spec.rb +19 -19
- data/spec/response_spec.rb +8 -8
- data/spec/spec_helper.rb +14 -11
- data/spec/stub_request_snippet_spec.rb +85 -37
- data/spec/support/webmock_server.rb +62 -0
- data/spec/typhoeus_hydra_spec.rb +53 -0
- data/spec/typhoeus_hydra_spec_helper.rb +50 -0
- data/spec/util/headers_spec.rb +5 -5
- data/spec/util/json_spec.rb +7 -0
- data/spec/util/uri_spec.rb +1 -1
- data/spec/vendor/addressable/lib/uri.rb +1 -0
- data/spec/vendor/crack/lib/crack.rb +1 -0
- data/spec/vendor/right_http_connection-1.2.4/History.txt +4 -4
- data/spec/vendor/right_http_connection-1.2.4/README.txt +4 -4
- data/spec/vendor/right_http_connection-1.2.4/Rakefile +3 -3
- data/spec/vendor/right_http_connection-1.2.4/lib/net_fix.rb +4 -4
- data/spec/vendor/right_http_connection-1.2.4/setup.rb +4 -4
- data/spec/webmock_shared.rb +375 -143
- data/spec/webmock_spec.rb +7 -0
- data/test/http_request.rb +24 -0
- data/test/shared_test.rb +47 -0
- data/test/test_helper.rb +6 -3
- data/test/test_webmock.rb +2 -67
- data/webmock.gemspec +8 -7
- metadata +153 -88
- data/lib/webmock/http_lib_adapters/patron.rb +0 -100
- data/spec/other_net_http_libs_spec.rb +0 -30
data/lib/webmock/http_lib_adapters/{em_http_request.rb → em_http_request/em_http_request_0_x.rb}
RENAMED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
if defined?(EventMachine::HttpRequest)
|
|
2
|
+
module WebMock
|
|
3
|
+
module HttpLibAdapters
|
|
4
|
+
class EmHttpRequestAdapter < HttpLibAdapter
|
|
5
|
+
adapter_for :em_http_request
|
|
2
6
|
|
|
3
|
-
|
|
4
|
-
|
|
7
|
+
OriginalHttpRequest = EventMachine::HttpRequest unless const_defined?(:OriginalHttpRequest)
|
|
8
|
+
|
|
9
|
+
def self.enable!
|
|
10
|
+
EventMachine.send(:remove_const, :HttpRequest)
|
|
11
|
+
EventMachine.send(:const_set, :HttpRequest, EventMachine::WebMockHttpRequest)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.disable!
|
|
15
|
+
EventMachine.send(:remove_const, :HttpRequest)
|
|
16
|
+
EventMachine.send(:const_set, :HttpRequest, OriginalHttpRequest)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
5
21
|
|
|
22
|
+
|
|
23
|
+
module EventMachine
|
|
6
24
|
class WebMockHttpRequest < EventMachine::HttpRequest
|
|
7
25
|
|
|
8
26
|
include HttpEncoding
|
|
@@ -126,19 +144,6 @@ if defined?(EventMachine::HttpRequest)
|
|
|
126
144
|
response_string << "" << body
|
|
127
145
|
response_string.join("\n")
|
|
128
146
|
end
|
|
129
|
-
|
|
130
|
-
def self.activate!
|
|
131
|
-
EventMachine.send(:remove_const, :HttpRequest)
|
|
132
|
-
EventMachine.send(:const_set, :HttpRequest, WebMockHttpRequest)
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def self.deactivate!
|
|
136
|
-
EventMachine.send(:remove_const, :HttpRequest)
|
|
137
|
-
EventMachine.send(:const_set, :HttpRequest, OriginalHttpRequest)
|
|
138
|
-
end
|
|
139
147
|
end
|
|
140
148
|
end
|
|
141
|
-
|
|
142
|
-
EventMachine::WebMockHttpRequest.activate!
|
|
143
|
-
|
|
144
149
|
end
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
if defined?(EventMachine::HttpClient)
|
|
2
|
+
module WebMock
|
|
3
|
+
module HttpLibAdapters
|
|
4
|
+
class EmHttpRequestAdapter < HttpLibAdapter
|
|
5
|
+
adapter_for :em_http_request
|
|
6
|
+
|
|
7
|
+
OriginalHttpClient = EventMachine::HttpClient unless const_defined?(:OriginalHttpClient)
|
|
8
|
+
OriginalHttpConnection = EventMachine::HttpConnection unless const_defined?(:OriginalHttpConnection)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def self.enable!
|
|
12
|
+
EventMachine.send(:remove_const, :HttpConnection)
|
|
13
|
+
EventMachine.send(:const_set, :HttpConnection, EventMachine::WebMockHttpConnection)
|
|
14
|
+
EventMachine.send(:remove_const, :HttpClient)
|
|
15
|
+
EventMachine.send(:const_set, :HttpClient, EventMachine::WebMockHttpClient)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.disable!
|
|
19
|
+
EventMachine.send(:remove_const, :HttpConnection)
|
|
20
|
+
EventMachine.send(:const_set, :HttpConnection, OriginalHttpConnection)
|
|
21
|
+
EventMachine.send(:remove_const, :HttpClient)
|
|
22
|
+
EventMachine.send(:const_set, :HttpClient, OriginalHttpClient)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
module EventMachine
|
|
29
|
+
|
|
30
|
+
if defined?(Synchrony)
|
|
31
|
+
# have to make the callbacks fire on the next tick in order
|
|
32
|
+
# to avoid the dreaded "double resume" exception
|
|
33
|
+
module HTTPMethods
|
|
34
|
+
%w[get head post delete put].each do |type|
|
|
35
|
+
class_eval %[
|
|
36
|
+
def #{type}(options = {}, &blk)
|
|
37
|
+
f = Fiber.current
|
|
38
|
+
|
|
39
|
+
conn = setup_request(:#{type}, options, &blk)
|
|
40
|
+
conn.callback { EM.next_tick { f.resume(conn) } }
|
|
41
|
+
conn.errback { EM.next_tick { f.resume(conn) } }
|
|
42
|
+
|
|
43
|
+
Fiber.yield
|
|
44
|
+
end
|
|
45
|
+
]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class WebMockHttpConnection < HttpConnection
|
|
51
|
+
def webmock_activate_connection(client)
|
|
52
|
+
request_signature = client.request_signature
|
|
53
|
+
|
|
54
|
+
if WebMock::StubRegistry.instance.registered_request?(request_signature)
|
|
55
|
+
conn = HttpStubConnection.new rand(10000)
|
|
56
|
+
post_init
|
|
57
|
+
|
|
58
|
+
@deferred = false
|
|
59
|
+
@conn = conn
|
|
60
|
+
|
|
61
|
+
conn.parent = self
|
|
62
|
+
conn.pending_connect_timeout = @connopts.connect_timeout
|
|
63
|
+
conn.comm_inactivity_timeout = @connopts.inactivity_timeout
|
|
64
|
+
|
|
65
|
+
finalize_request(client)
|
|
66
|
+
@conn.set_deferred_status :succeeded
|
|
67
|
+
elsif WebMock.net_connect_allowed?(request_signature.uri)
|
|
68
|
+
real_activate_connection(client)
|
|
69
|
+
else
|
|
70
|
+
raise WebMock::NetConnectNotAllowedError.new(request_signature)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
alias_method :real_activate_connection, :activate_connection
|
|
74
|
+
alias_method :activate_connection, :webmock_activate_connection
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
class WebMockHttpClient < EventMachine::HttpClient
|
|
78
|
+
include HttpEncoding
|
|
79
|
+
|
|
80
|
+
def uri
|
|
81
|
+
@req.uri
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def setup(response, uri, error = nil)
|
|
85
|
+
@last_effective_url = @uri = uri
|
|
86
|
+
if error
|
|
87
|
+
on_error(error)
|
|
88
|
+
fail(self)
|
|
89
|
+
else
|
|
90
|
+
@conn.receive_data(response)
|
|
91
|
+
succeed(self)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def send_request_with_webmock(head, body)
|
|
96
|
+
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
|
97
|
+
|
|
98
|
+
if WebMock::StubRegistry.instance.registered_request?(request_signature)
|
|
99
|
+
webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
|
|
100
|
+
on_error("WebMock timeout error") if webmock_response.should_timeout
|
|
101
|
+
WebMock::CallbackRegistry.invoke_callbacks({:lib => :em_http_request}, request_signature, webmock_response)
|
|
102
|
+
EM.next_tick {
|
|
103
|
+
setup(make_raw_response(webmock_response), @uri,
|
|
104
|
+
webmock_response.should_timeout ? "WebMock timeout error" : nil)
|
|
105
|
+
}
|
|
106
|
+
self
|
|
107
|
+
elsif WebMock.net_connect_allowed?(request_signature.uri)
|
|
108
|
+
send_request_without_webmock(head, body)
|
|
109
|
+
callback {
|
|
110
|
+
if WebMock::CallbackRegistry.any_callbacks?
|
|
111
|
+
webmock_response = build_webmock_response
|
|
112
|
+
WebMock::CallbackRegistry.invoke_callbacks(
|
|
113
|
+
{:lib => :em_http_request, :real_request => true},
|
|
114
|
+
request_signature,
|
|
115
|
+
webmock_response)
|
|
116
|
+
end
|
|
117
|
+
}
|
|
118
|
+
self
|
|
119
|
+
else
|
|
120
|
+
raise WebMock::NetConnectNotAllowedError.new(request_signature)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
alias_method :send_request_without_webmock, :send_request
|
|
125
|
+
alias_method :send_request, :send_request_with_webmock
|
|
126
|
+
|
|
127
|
+
def request_signature
|
|
128
|
+
@request_signature ||= build_request_signature
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
def build_webmock_response
|
|
134
|
+
webmock_response = WebMock::Response.new
|
|
135
|
+
webmock_response.status = [response_header.status, response_header.http_reason]
|
|
136
|
+
webmock_response.headers = response_header
|
|
137
|
+
webmock_response.body = response
|
|
138
|
+
webmock_response
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def build_request_signature
|
|
142
|
+
headers, body = @req.headers, @req.body
|
|
143
|
+
|
|
144
|
+
@conn.middleware.select {|m| m.respond_to?(:request) }.each do |m|
|
|
145
|
+
headers, body = m.request(self, headers, body)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
method = @req.method
|
|
149
|
+
uri = @req.uri
|
|
150
|
+
auth = @req.proxy[:authorization]
|
|
151
|
+
query = @req.query
|
|
152
|
+
|
|
153
|
+
if auth
|
|
154
|
+
userinfo = auth.join(':')
|
|
155
|
+
userinfo = WebMock::Util::URI.encode_unsafe_chars_in_userinfo(userinfo)
|
|
156
|
+
if @req
|
|
157
|
+
@req.proxy.reject! {|k,v| t.to_s == 'authorization' }
|
|
158
|
+
else
|
|
159
|
+
options.reject! {|k,v| k.to_s == 'authorization' } #we added it to url userinfo
|
|
160
|
+
end
|
|
161
|
+
uri.userinfo = userinfo
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
uri.query = encode_query(@req.uri, query).slice(/\?(.*)/, 1)
|
|
165
|
+
|
|
166
|
+
WebMock::RequestSignature.new(
|
|
167
|
+
method.downcase.to_sym,
|
|
168
|
+
uri.to_s,
|
|
169
|
+
:body => body,
|
|
170
|
+
:headers => headers
|
|
171
|
+
)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def make_raw_response(response)
|
|
175
|
+
response.raise_error_if_any
|
|
176
|
+
|
|
177
|
+
status, headers, body = response.status, response.headers, response.body
|
|
178
|
+
headers ||= {}
|
|
179
|
+
|
|
180
|
+
response_string = []
|
|
181
|
+
response_string << "HTTP/1.1 #{status[0]} #{status[1]}"
|
|
182
|
+
|
|
183
|
+
headers["Content-Length"] = body.length unless headers["Content-Length"]
|
|
184
|
+
headers.each do |header, value|
|
|
185
|
+
value = value.join(", ") if value.is_a?(Array)
|
|
186
|
+
|
|
187
|
+
# WebMock's internal processing will not handle the body
|
|
188
|
+
# correctly if the header indicates that it is chunked, unless
|
|
189
|
+
# we also create all the chunks.
|
|
190
|
+
# It's far easier just to remove the header.
|
|
191
|
+
next if header =~ /transfer-encoding/i && value =~/chunked/i
|
|
192
|
+
|
|
193
|
+
response_string << "#{header}: #{value}"
|
|
194
|
+
end if headers
|
|
195
|
+
|
|
196
|
+
response_string << "" << body
|
|
197
|
+
response_string.join("\n")
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'em-http-request'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
# em-http-request not found
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
if defined?(EventMachine::HttpConnection)
|
|
8
|
+
require File.expand_path(File.dirname(__FILE__) + '/em_http_request/em_http_request_1_x')
|
|
9
|
+
else
|
|
10
|
+
require File.expand_path(File.dirname(__FILE__) + '/em_http_request/em_http_request_0_x')
|
|
11
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module WebMock
|
|
2
|
+
class HttpLibAdapterRegistry
|
|
3
|
+
include Singleton
|
|
4
|
+
|
|
5
|
+
attr_accessor :http_lib_adapters
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@http_lib_adapters = {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def register(lib, adapter)
|
|
12
|
+
@http_lib_adapters[lib] = adapter
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def each_adapter(&block)
|
|
16
|
+
@http_lib_adapters.each(&block)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -1,6 +1,33 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'httpclient'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
# httpclient not found
|
|
5
|
+
end
|
|
6
|
+
|
|
1
7
|
if defined?(::HTTPClient)
|
|
2
8
|
|
|
3
|
-
|
|
9
|
+
module WebMock
|
|
10
|
+
module HttpLibAdapters
|
|
11
|
+
class HTTPClientAdapter < HttpLibAdapter
|
|
12
|
+
adapter_for :httpclient
|
|
13
|
+
|
|
14
|
+
OriginalHttpClient = ::HTTPClient unless const_defined?(:OriginalHttpClient)
|
|
15
|
+
|
|
16
|
+
def self.enable!
|
|
17
|
+
Object.send(:remove_const, :HTTPClient)
|
|
18
|
+
Object.send(:const_set, :HTTPClient, WebMockHTTPClient)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.disable!
|
|
22
|
+
Object.send(:remove_const, :HTTPClient)
|
|
23
|
+
Object.send(:const_set, :HTTPClient, OriginalHttpClient)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class WebMockHTTPClient < HTTPClient
|
|
4
31
|
|
|
5
32
|
def do_get_block_with_webmock(req, proxy, conn, &block)
|
|
6
33
|
do_get_with_webmock(req, proxy, conn, false, &block)
|
|
@@ -20,7 +47,7 @@ if defined?(::HTTPClient)
|
|
|
20
47
|
response = build_httpclient_response(webmock_response, stream, &block)
|
|
21
48
|
res = conn.push(response)
|
|
22
49
|
WebMock::CallbackRegistry.invoke_callbacks(
|
|
23
|
-
{:lib => :
|
|
50
|
+
{:lib => :httpclient}, request_signature, webmock_response)
|
|
24
51
|
res
|
|
25
52
|
elsif WebMock.net_connect_allowed?(request_signature.uri)
|
|
26
53
|
res = if stream
|
|
@@ -33,7 +60,7 @@ if defined?(::HTTPClient)
|
|
|
33
60
|
if WebMock::CallbackRegistry.any_callbacks?
|
|
34
61
|
webmock_response = build_webmock_response(res)
|
|
35
62
|
WebMock::CallbackRegistry.invoke_callbacks(
|
|
36
|
-
{:lib => :
|
|
63
|
+
{:lib => :httpclient, :real_request => true}, request_signature,
|
|
37
64
|
webmock_response)
|
|
38
65
|
end
|
|
39
66
|
res
|
|
@@ -45,7 +72,7 @@ if defined?(::HTTPClient)
|
|
|
45
72
|
def do_request_async_with_webmock(method, uri, query, body, extheader)
|
|
46
73
|
req = create_request(method, uri, query, body, extheader)
|
|
47
74
|
request_signature = build_request_signature(req)
|
|
48
|
-
|
|
75
|
+
|
|
49
76
|
if WebMock::StubRegistry.instance.registered_request?(request_signature) ||
|
|
50
77
|
WebMock.net_connect_allowed?(request_signature.uri)
|
|
51
78
|
do_request_async_without_webmock(method, uri, query, body, extheader)
|
|
@@ -70,7 +97,7 @@ if defined?(::HTTPClient)
|
|
|
70
97
|
response.reason=webmock_response.status[1]
|
|
71
98
|
webmock_response.headers.to_a.each { |name, value| response.header.set(name, value) }
|
|
72
99
|
|
|
73
|
-
raise HTTPClient::TimeoutError if webmock_response.should_timeout
|
|
100
|
+
raise HTTPClient::TimeoutError if webmock_response.should_timeout
|
|
74
101
|
webmock_response.raise_error_if_any
|
|
75
102
|
|
|
76
103
|
block.call(nil, body) if block
|
|
@@ -78,7 +105,7 @@ if defined?(::HTTPClient)
|
|
|
78
105
|
response
|
|
79
106
|
end
|
|
80
107
|
end
|
|
81
|
-
|
|
108
|
+
|
|
82
109
|
def build_webmock_response(httpclient_response)
|
|
83
110
|
webmock_response = WebMock::Response.new
|
|
84
111
|
webmock_response.status = [httpclient_response.status, httpclient_response.reason]
|
|
@@ -102,8 +129,8 @@ if defined?(::HTTPClient)
|
|
|
102
129
|
|
|
103
130
|
auth = www_auth.basic_auth
|
|
104
131
|
auth.challenge(req.header.request_uri, nil)
|
|
105
|
-
|
|
106
|
-
headers = req.header.all.inject({}) do |headers, header|
|
|
132
|
+
|
|
133
|
+
headers = req.header.all.inject({}) do |headers, header|
|
|
107
134
|
headers[header[0]] ||= [];
|
|
108
135
|
headers[header[0]] << header[1]
|
|
109
136
|
headers
|
|
@@ -3,6 +3,36 @@ require 'net/https'
|
|
|
3
3
|
require 'stringio'
|
|
4
4
|
require File.join(File.dirname(__FILE__), 'net_http_response')
|
|
5
5
|
|
|
6
|
+
|
|
7
|
+
module WebMock
|
|
8
|
+
module HttpLibAdapters
|
|
9
|
+
class NetHttpAdapter < HttpLibAdapter
|
|
10
|
+
adapter_for :net_http
|
|
11
|
+
|
|
12
|
+
OriginalNetHTTP = Net::HTTP unless const_defined?(:OriginalNetHTTP)
|
|
13
|
+
OriginalNetBufferedIO = Net::BufferedIO unless const_defined?(:OriginalNetBufferedIO)
|
|
14
|
+
|
|
15
|
+
def self.enable!
|
|
16
|
+
Net.send(:remove_const, :BufferedIO)
|
|
17
|
+
Net.send(:remove_const, :HTTP)
|
|
18
|
+
Net.send(:remove_const, :HTTPSession)
|
|
19
|
+
Net.send(:const_set, :HTTP, Net::WebMockNetHTTP)
|
|
20
|
+
Net.send(:const_set, :HTTPSession, Net::WebMockNetHTTP)
|
|
21
|
+
Net.send(:const_set, :BufferedIO, Net::WebMockNetBufferedIO)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.disable!
|
|
25
|
+
Net.send(:remove_const, :BufferedIO)
|
|
26
|
+
Net.send(:remove_const, :HTTP)
|
|
27
|
+
Net.send(:remove_const, :HTTPSession)
|
|
28
|
+
Net.send(:const_set, :HTTP, OriginalNetHTTP)
|
|
29
|
+
Net.send(:const_set, :HTTPSession, OriginalNetHTTP)
|
|
30
|
+
Net.send(:const_set, :BufferedIO, OriginalNetBufferedIO)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
6
36
|
class StubSocket #:nodoc:
|
|
7
37
|
|
|
8
38
|
def initialize(*args)
|
|
@@ -19,7 +49,7 @@ end
|
|
|
19
49
|
|
|
20
50
|
module Net #:nodoc: all
|
|
21
51
|
|
|
22
|
-
class BufferedIO
|
|
52
|
+
class WebMockNetBufferedIO < BufferedIO
|
|
23
53
|
def initialize_with_webmock(io, debug_output = nil)
|
|
24
54
|
@read_timeout = 60
|
|
25
55
|
@rbuf = ''
|
|
@@ -37,7 +67,7 @@ module Net #:nodoc: all
|
|
|
37
67
|
alias_method :initialize, :initialize_with_webmock
|
|
38
68
|
end
|
|
39
69
|
|
|
40
|
-
class HTTP
|
|
70
|
+
class WebMockNetHTTP < HTTP
|
|
41
71
|
class << self
|
|
42
72
|
def socket_type_with_webmock
|
|
43
73
|
StubSocket
|
|
@@ -58,16 +88,27 @@ module Net #:nodoc: all
|
|
|
58
88
|
{:lib => :net_http}, request_signature, webmock_response)
|
|
59
89
|
build_net_http_response(webmock_response, &block)
|
|
60
90
|
elsif WebMock.net_connect_allowed?(request_signature.uri)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
91
|
+
check_right_http_connection
|
|
92
|
+
after_request = lambda do |response|
|
|
93
|
+
if WebMock::CallbackRegistry.any_callbacks?
|
|
94
|
+
webmock_response = build_webmock_response(response)
|
|
95
|
+
WebMock::CallbackRegistry.invoke_callbacks(
|
|
96
|
+
{:lib => :net_http, :real_request => true}, request_signature, webmock_response)
|
|
97
|
+
end
|
|
98
|
+
response.extend Net::WebMockHTTPResponse
|
|
99
|
+
block.call response if block
|
|
100
|
+
response
|
|
101
|
+
end
|
|
102
|
+
response = if (started? && !WebMock::Config.instance.net_http_connect_on_start) || !started?
|
|
103
|
+
@started = false #otherwise start_with_connect wouldn't execute and connect
|
|
104
|
+
start_with_connect {
|
|
105
|
+
response = request_without_webmock(request, nil)
|
|
106
|
+
after_request.call(response)
|
|
107
|
+
}
|
|
108
|
+
else
|
|
109
|
+
response = request_without_webmock(request, nil)
|
|
110
|
+
after_request.call(response)
|
|
67
111
|
end
|
|
68
|
-
response.extend WebMock::Net::HTTPResponse
|
|
69
|
-
yield response if block_given?
|
|
70
|
-
response
|
|
71
112
|
else
|
|
72
113
|
raise WebMock::NetConnectNotAllowedError.new(request_signature)
|
|
73
114
|
end
|
|
@@ -75,33 +116,43 @@ module Net #:nodoc: all
|
|
|
75
116
|
alias_method :request_without_webmock, :request
|
|
76
117
|
alias_method :request, :request_with_webmock
|
|
77
118
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
119
|
+
def start_without_connect
|
|
120
|
+
raise IOError, 'HTTP session already opened' if @started
|
|
121
|
+
if block_given?
|
|
122
|
+
begin
|
|
123
|
+
@started = true
|
|
124
|
+
return yield(self)
|
|
125
|
+
ensure
|
|
126
|
+
do_finish
|
|
127
|
+
end
|
|
83
128
|
end
|
|
129
|
+
@started = true
|
|
130
|
+
self
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def start_with_conditional_connect(&block)
|
|
84
134
|
if WebMock::Config.instance.net_http_connect_on_start
|
|
85
|
-
|
|
135
|
+
start_with_connect(&block)
|
|
136
|
+
else
|
|
137
|
+
start_without_connect(&block)
|
|
86
138
|
end
|
|
87
|
-
nil
|
|
88
139
|
end
|
|
89
|
-
alias_method :
|
|
90
|
-
alias_method :
|
|
140
|
+
alias_method :start_with_connect, :start
|
|
141
|
+
alias_method :start, :start_with_conditional_connect
|
|
91
142
|
|
|
92
143
|
def build_net_http_response(webmock_response, &block)
|
|
93
144
|
response = Net::HTTPResponse.send(:response_class, webmock_response.status[0].to_s).new("1.0", webmock_response.status[0].to_s, webmock_response.status[1])
|
|
94
145
|
response.instance_variable_set(:@body, webmock_response.body)
|
|
95
|
-
webmock_response.headers.to_a.each do |name, values|
|
|
146
|
+
webmock_response.headers.to_a.each do |name, values|
|
|
96
147
|
values = [values] unless values.is_a?(Array)
|
|
97
148
|
values.each do |value|
|
|
98
149
|
response.add_field(name, value)
|
|
99
150
|
end
|
|
100
|
-
end
|
|
151
|
+
end
|
|
101
152
|
|
|
102
153
|
response.instance_variable_set(:@read, true)
|
|
103
154
|
|
|
104
|
-
response.extend
|
|
155
|
+
response.extend Net::WebMockHTTPResponse
|
|
105
156
|
|
|
106
157
|
raise Timeout::Error, "execution expired" if webmock_response.should_timeout
|
|
107
158
|
|
|
@@ -111,18 +162,26 @@ module Net #:nodoc: all
|
|
|
111
162
|
|
|
112
163
|
response
|
|
113
164
|
end
|
|
114
|
-
|
|
165
|
+
|
|
115
166
|
def build_webmock_response(net_http_response)
|
|
116
167
|
webmock_response = WebMock::Response.new
|
|
117
168
|
webmock_response.status = [
|
|
118
169
|
net_http_response.code.to_i,
|
|
119
170
|
net_http_response.message]
|
|
120
171
|
webmock_response.headers = net_http_response.to_hash
|
|
121
|
-
webmock_response.body = net_http_response.body
|
|
172
|
+
webmock_response.body = net_http_response.body
|
|
122
173
|
webmock_response
|
|
123
174
|
end
|
|
124
175
|
|
|
176
|
+
|
|
177
|
+
def check_right_http_connection
|
|
178
|
+
unless @@alredy_checked_for_right_http_connection ||= false
|
|
179
|
+
WebMock::NetHTTPUtility.puts_warning_for_right_http_if_needed
|
|
180
|
+
@@alredy_checked_for_right_http_connection = true
|
|
181
|
+
end
|
|
182
|
+
end
|
|
125
183
|
end
|
|
184
|
+
Net::WebMockNetHTTP.version_1_2
|
|
126
185
|
|
|
127
186
|
end
|
|
128
187
|
|