webmock 3.0.1 → 3.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +558 -2
- data/README.md +200 -42
- data/lib/webmock/api.rb +14 -0
- data/lib/webmock/assertion_failure.rb +2 -0
- data/lib/webmock/callback_registry.rb +2 -0
- data/lib/webmock/config.rb +2 -0
- data/lib/webmock/cucumber.rb +2 -0
- data/lib/webmock/deprecation.rb +2 -0
- data/lib/webmock/errors.rb +2 -0
- data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +223 -0
- data/lib/webmock/http_lib_adapters/curb_adapter.rb +21 -5
- data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +20 -9
- data/lib/webmock/http_lib_adapters/excon_adapter.rb +7 -2
- data/lib/webmock/http_lib_adapters/http_lib_adapter.rb +2 -0
- data/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +2 -0
- data/lib/webmock/http_lib_adapters/http_rb/client.rb +4 -1
- data/lib/webmock/http_lib_adapters/http_rb/request.rb +19 -1
- data/lib/webmock/http_lib_adapters/http_rb/response.rb +29 -3
- data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +11 -3
- data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +9 -3
- data/lib/webmock/http_lib_adapters/http_rb_adapter.rb +2 -0
- data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +30 -9
- data/lib/webmock/http_lib_adapters/manticore_adapter.rb +35 -15
- data/lib/webmock/http_lib_adapters/net_http.rb +38 -89
- data/lib/webmock/http_lib_adapters/net_http_response.rb +3 -1
- data/lib/webmock/http_lib_adapters/patron_adapter.rb +6 -4
- data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +18 -2
- data/lib/webmock/matchers/any_arg_matcher.rb +15 -0
- data/lib/webmock/matchers/hash_argument_matcher.rb +23 -0
- data/lib/webmock/matchers/hash_excluding_matcher.rb +17 -0
- data/lib/webmock/matchers/hash_including_matcher.rb +6 -23
- data/lib/webmock/minitest.rb +2 -0
- data/lib/webmock/rack_response.rb +3 -1
- data/lib/webmock/request_body_diff.rb +3 -1
- data/lib/webmock/request_execution_verifier.rb +4 -3
- data/lib/webmock/request_pattern.rb +132 -52
- data/lib/webmock/request_registry.rb +3 -1
- data/lib/webmock/request_signature.rb +5 -3
- data/lib/webmock/request_signature_snippet.rb +6 -4
- data/lib/webmock/request_stub.rb +34 -0
- data/lib/webmock/response.rb +22 -14
- data/lib/webmock/responses_sequence.rb +2 -0
- data/lib/webmock/rspec/matchers/request_pattern_matcher.rb +2 -0
- data/lib/webmock/rspec/matchers/webmock_matcher.rb +2 -0
- data/lib/webmock/rspec/matchers.rb +2 -0
- data/lib/webmock/rspec.rb +12 -3
- data/lib/webmock/stub_registry.rb +28 -11
- data/lib/webmock/stub_request_snippet.rb +12 -6
- data/lib/webmock/test_unit.rb +3 -3
- data/lib/webmock/util/hash_counter.rb +15 -9
- data/lib/webmock/util/hash_keys_stringifier.rb +2 -0
- data/lib/webmock/util/hash_validator.rb +2 -0
- data/lib/webmock/util/headers.rb +39 -11
- data/lib/webmock/util/json.rb +3 -2
- data/lib/webmock/util/query_mapper.rb +11 -7
- data/lib/webmock/util/uri.rb +13 -11
- data/lib/webmock/util/values_stringifier.rb +22 -0
- data/lib/webmock/util/version_checker.rb +7 -5
- data/lib/webmock/version.rb +3 -1
- data/lib/webmock/webmock.rb +22 -3
- data/lib/webmock.rb +55 -48
- metadata +106 -175
- data/.gemtest +0 -0
- data/.gitignore +0 -34
- data/.rspec-tm +0 -2
- data/.travis.yml +0 -20
- data/Gemfile +0 -9
- data/Rakefile +0 -30
- data/minitest/test_helper.rb +0 -34
- data/minitest/test_webmock.rb +0 -9
- data/minitest/webmock_spec.rb +0 -60
- data/spec/acceptance/curb/curb_spec.rb +0 -466
- data/spec/acceptance/curb/curb_spec_helper.rb +0 -147
- data/spec/acceptance/em_http_request/em_http_request_spec.rb +0 -406
- data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +0 -77
- data/spec/acceptance/excon/excon_spec.rb +0 -75
- data/spec/acceptance/excon/excon_spec_helper.rb +0 -50
- data/spec/acceptance/http_rb/http_rb_spec.rb +0 -73
- data/spec/acceptance/http_rb/http_rb_spec_helper.rb +0 -51
- data/spec/acceptance/httpclient/httpclient_spec.rb +0 -210
- data/spec/acceptance/httpclient/httpclient_spec_helper.rb +0 -57
- data/spec/acceptance/manticore/manticore_spec.rb +0 -56
- data/spec/acceptance/manticore/manticore_spec_helper.rb +0 -35
- data/spec/acceptance/net_http/net_http_shared.rb +0 -153
- data/spec/acceptance/net_http/net_http_spec.rb +0 -317
- data/spec/acceptance/net_http/net_http_spec_helper.rb +0 -64
- data/spec/acceptance/net_http/real_net_http_spec.rb +0 -20
- data/spec/acceptance/patron/patron_spec.rb +0 -118
- data/spec/acceptance/patron/patron_spec_helper.rb +0 -54
- data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +0 -313
- data/spec/acceptance/shared/callbacks.rb +0 -147
- data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +0 -36
- data/spec/acceptance/shared/enabling_and_disabling_webmock.rb +0 -95
- data/spec/acceptance/shared/precedence_of_stubs.rb +0 -15
- data/spec/acceptance/shared/request_expectations.rb +0 -916
- data/spec/acceptance/shared/returning_declared_responses.rb +0 -388
- data/spec/acceptance/shared/stubbing_requests.rb +0 -583
- data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +0 -135
- data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +0 -60
- data/spec/acceptance/webmock_shared.rb +0 -41
- data/spec/fixtures/test.txt +0 -1
- data/spec/quality_spec.rb +0 -84
- data/spec/spec_helper.rb +0 -48
- data/spec/support/example_curl_output.txt +0 -22
- data/spec/support/failures.rb +0 -9
- data/spec/support/my_rack_app.rb +0 -53
- data/spec/support/network_connection.rb +0 -19
- data/spec/support/webmock_server.rb +0 -69
- data/spec/unit/api_spec.rb +0 -75
- data/spec/unit/errors_spec.rb +0 -129
- data/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +0 -17
- data/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +0 -12
- data/spec/unit/matchers/hash_including_matcher_spec.rb +0 -87
- data/spec/unit/rack_response_spec.rb +0 -112
- data/spec/unit/request_body_diff_spec.rb +0 -90
- data/spec/unit/request_execution_verifier_spec.rb +0 -208
- data/spec/unit/request_pattern_spec.rb +0 -590
- data/spec/unit/request_registry_spec.rb +0 -95
- data/spec/unit/request_signature_snippet_spec.rb +0 -89
- data/spec/unit/request_signature_spec.rb +0 -155
- data/spec/unit/request_stub_spec.rb +0 -199
- data/spec/unit/response_spec.rb +0 -282
- data/spec/unit/stub_registry_spec.rb +0 -103
- data/spec/unit/stub_request_snippet_spec.rb +0 -95
- data/spec/unit/util/hash_counter_spec.rb +0 -39
- data/spec/unit/util/hash_keys_stringifier_spec.rb +0 -27
- data/spec/unit/util/headers_spec.rb +0 -28
- data/spec/unit/util/json_spec.rb +0 -33
- data/spec/unit/util/query_mapper_spec.rb +0 -144
- data/spec/unit/util/uri_spec.rb +0 -299
- data/spec/unit/util/version_checker_spec.rb +0 -65
- data/spec/unit/webmock_spec.rb +0 -11
- data/test/http_request.rb +0 -24
- data/test/shared_test.rb +0 -95
- data/test/test_helper.rb +0 -23
- data/test/test_webmock.rb +0 -6
- data/webmock.gemspec +0 -46
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'curb'
|
3
5
|
rescue LoadError
|
@@ -5,7 +7,7 @@ rescue LoadError
|
|
5
7
|
end
|
6
8
|
|
7
9
|
if defined?(Curl)
|
8
|
-
WebMock::VersionChecker.new('Curb', Curl::CURB_VERSION, '0.7.16', '0.
|
10
|
+
WebMock::VersionChecker.new('Curb', Curl::CURB_VERSION, '0.7.16', '1.0.1', ['0.8.7']).check_version!
|
9
11
|
|
10
12
|
module WebMock
|
11
13
|
module HttpLibAdapters
|
@@ -54,7 +56,6 @@ if defined?(Curl)
|
|
54
56
|
|
55
57
|
module Curl
|
56
58
|
class WebMockCurlEasy < Curl::Easy
|
57
|
-
|
58
59
|
def curb_or_webmock
|
59
60
|
request_signature = build_request_signature
|
60
61
|
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
@@ -129,7 +130,7 @@ if defined?(Curl)
|
|
129
130
|
def headers_as_hash(headers)
|
130
131
|
if headers.is_a?(Array)
|
131
132
|
headers.inject({}) {|hash, header|
|
132
|
-
name, value = header.split(":").map(&:strip)
|
133
|
+
name, value = header.split(":", 2).map(&:strip)
|
133
134
|
hash[name] = value
|
134
135
|
hash
|
135
136
|
}
|
@@ -153,7 +154,7 @@ if defined?(Curl)
|
|
153
154
|
@body_str = webmock_response.body
|
154
155
|
@response_code = webmock_response.status[0]
|
155
156
|
|
156
|
-
@header_str = "HTTP/1.1 #{webmock_response.status[0]} #{webmock_response.status[1]}\r\n"
|
157
|
+
@header_str = "HTTP/1.1 #{webmock_response.status[0]} #{webmock_response.status[1]}\r\n".dup
|
157
158
|
|
158
159
|
@on_debug.call(@header_str, 1) if defined?( @on_debug )
|
159
160
|
|
@@ -183,7 +184,7 @@ if defined?(Curl)
|
|
183
184
|
self.url = location
|
184
185
|
|
185
186
|
curb_or_webmock do
|
186
|
-
send(
|
187
|
+
send( :http, {'method' => @webmock_method} )
|
187
188
|
end
|
188
189
|
|
189
190
|
self.url = first_url
|
@@ -271,6 +272,8 @@ if defined?(Curl)
|
|
271
272
|
def perform
|
272
273
|
@webmock_method ||= :get
|
273
274
|
curb_or_webmock { super }
|
275
|
+
ensure
|
276
|
+
reset_webmock_method
|
274
277
|
end
|
275
278
|
|
276
279
|
def put_data= data
|
@@ -332,6 +335,19 @@ if defined?(Curl)
|
|
332
335
|
end
|
333
336
|
METHOD
|
334
337
|
end
|
338
|
+
|
339
|
+
def reset_webmock_method
|
340
|
+
@webmock_method = :get
|
341
|
+
end
|
342
|
+
|
343
|
+
def reset
|
344
|
+
instance_variable_set(:@body_str, nil)
|
345
|
+
instance_variable_set(:@content_type, nil)
|
346
|
+
instance_variable_set(:@header_str, nil)
|
347
|
+
instance_variable_set(:@last_effective_url, nil)
|
348
|
+
instance_variable_set(:@response_code, nil)
|
349
|
+
super
|
350
|
+
end
|
335
351
|
end
|
336
352
|
end
|
337
353
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'em-http-request'
|
3
5
|
rescue LoadError
|
@@ -99,6 +101,11 @@ if defined?(EventMachine::HttpClient)
|
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
104
|
+
def connection_completed
|
105
|
+
@state = :response_header
|
106
|
+
send_request(*headers_and_body_processed_by_middleware)
|
107
|
+
end
|
108
|
+
|
102
109
|
def send_request(head, body)
|
103
110
|
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
104
111
|
|
@@ -107,7 +114,7 @@ if defined?(EventMachine::HttpClient)
|
|
107
114
|
@uri ||= nil
|
108
115
|
EM.next_tick {
|
109
116
|
setup(make_raw_response(stubbed_webmock_response), @uri,
|
110
|
-
stubbed_webmock_response.should_timeout ?
|
117
|
+
stubbed_webmock_response.should_timeout ? Errno::ETIMEDOUT : nil)
|
111
118
|
}
|
112
119
|
self
|
113
120
|
elsif WebMock.net_connect_allowed?(request_signature.uri)
|
@@ -149,7 +156,7 @@ if defined?(EventMachine::HttpClient)
|
|
149
156
|
raw_cookie = response_header.cookie
|
150
157
|
raw_cookie = [raw_cookie] if raw_cookie.is_a? String
|
151
158
|
|
152
|
-
cookie = raw_cookie.
|
159
|
+
cookie = raw_cookie.detect { |c| c.start_with? name }
|
153
160
|
cookie and cookie.split('=', 2)[1]
|
154
161
|
end
|
155
162
|
|
@@ -163,12 +170,18 @@ if defined?(EventMachine::HttpClient)
|
|
163
170
|
webmock_response
|
164
171
|
end
|
165
172
|
|
166
|
-
def
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
173
|
+
def headers_and_body_processed_by_middleware
|
174
|
+
@headers_and_body_processed_by_middleware ||= begin
|
175
|
+
head, body = build_request, @req.body
|
176
|
+
@conn.middleware.each do |m|
|
177
|
+
head, body = m.request(self, head, body) if m.respond_to?(:request)
|
178
|
+
end
|
179
|
+
[head, body]
|
171
180
|
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def build_request_signature
|
184
|
+
headers, body = headers_and_body_processed_by_middleware
|
172
185
|
|
173
186
|
method = @req.method
|
174
187
|
uri = @req.uri.clone
|
@@ -178,8 +191,6 @@ if defined?(EventMachine::HttpClient)
|
|
178
191
|
|
179
192
|
body = form_encode_body(body) if body.is_a?(Hash)
|
180
193
|
|
181
|
-
headers = @req.headers
|
182
|
-
|
183
194
|
if headers['authorization'] && headers['authorization'].is_a?(Array)
|
184
195
|
headers['Authorization'] = WebMock::Util::Headers.basic_auth_header(headers.delete('authorization'))
|
185
196
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'excon'
|
3
5
|
rescue LoadError
|
@@ -92,7 +94,7 @@ if defined?(Excon)
|
|
92
94
|
end
|
93
95
|
|
94
96
|
def self.to_query(hash)
|
95
|
-
string = ""
|
97
|
+
string = "".dup
|
96
98
|
for key, values in hash
|
97
99
|
if values.nil?
|
98
100
|
string << key.to_s << '&'
|
@@ -152,11 +154,14 @@ if defined?(Excon)
|
|
152
154
|
end
|
153
155
|
|
154
156
|
Excon::Connection.class_eval do
|
155
|
-
def self.new(args)
|
157
|
+
def self.new(args = {})
|
156
158
|
args.delete(:__construction_args)
|
157
159
|
super(args).tap do |instance|
|
158
160
|
instance.data[:__construction_args] = args
|
159
161
|
end
|
160
162
|
end
|
161
163
|
end
|
164
|
+
|
165
|
+
# Suppresses Excon connection argument validation warning
|
166
|
+
Excon::VALID_CONNECTION_KEYS << :__construction_args
|
162
167
|
end
|
@@ -1,10 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HTTP
|
2
4
|
class Client
|
3
5
|
alias_method :__perform__, :perform
|
4
6
|
|
5
7
|
def perform(request, options)
|
6
8
|
return __perform__(request, options) unless webmock_enabled?
|
7
|
-
|
9
|
+
|
10
|
+
WebMockPerform.new(request, options) { __perform__(request, options) }.exec
|
8
11
|
end
|
9
12
|
|
10
13
|
def webmock_enabled?
|
@@ -1,9 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HTTP
|
2
4
|
class Request
|
3
5
|
def webmock_signature
|
6
|
+
request_body = nil
|
7
|
+
|
8
|
+
if defined?(HTTP::Request::Body)
|
9
|
+
request_body = String.new
|
10
|
+
first_chunk_encoding = nil
|
11
|
+
body.each do |part|
|
12
|
+
request_body << part
|
13
|
+
first_chunk_encoding ||= part.encoding
|
14
|
+
end
|
15
|
+
|
16
|
+
request_body.force_encoding(first_chunk_encoding) if first_chunk_encoding
|
17
|
+
request_body
|
18
|
+
else
|
19
|
+
request_body = body
|
20
|
+
end
|
21
|
+
|
4
22
|
::WebMock::RequestSignature.new(verb, uri.to_s, {
|
5
23
|
headers: headers.to_h,
|
6
|
-
body:
|
24
|
+
body: request_body
|
7
25
|
})
|
8
26
|
end
|
9
27
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HTTP
|
2
4
|
class Response
|
3
5
|
def to_webmock
|
@@ -11,20 +13,44 @@ module HTTP
|
|
11
13
|
end
|
12
14
|
|
13
15
|
class << self
|
14
|
-
def from_webmock(webmock_response, request_signature = nil)
|
16
|
+
def from_webmock(request, webmock_response, request_signature = nil)
|
15
17
|
status = Status.new(webmock_response.status.first)
|
16
18
|
headers = webmock_response.headers || {}
|
17
|
-
body = Body.new Streamer.new webmock_response.body
|
18
19
|
uri = normalize_uri(request_signature && request_signature.uri)
|
19
20
|
|
21
|
+
# HTTP.rb 3.0+ uses a keyword argument to pass the encoding, but 1.x
|
22
|
+
# and 2.x use a positional argument, and 0.x don't support supplying
|
23
|
+
# the encoding.
|
24
|
+
body = if HTTP::VERSION < "1.0.0"
|
25
|
+
Body.new(Streamer.new(webmock_response.body))
|
26
|
+
elsif HTTP::VERSION < "3.0.0"
|
27
|
+
Body.new(Streamer.new(webmock_response.body), webmock_response.body.encoding)
|
28
|
+
else
|
29
|
+
Body.new(
|
30
|
+
Streamer.new(webmock_response.body, encoding: webmock_response.body.encoding),
|
31
|
+
encoding: webmock_response.body.encoding
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
20
35
|
return new(status, "1.1", headers, body, uri) if HTTP::VERSION < "1.0.0"
|
21
36
|
|
37
|
+
# 5.0.0 had a breaking change to require request instead of uri.
|
38
|
+
if HTTP::VERSION < '5.0.0'
|
39
|
+
return new({
|
40
|
+
status: status,
|
41
|
+
version: "1.1",
|
42
|
+
headers: headers,
|
43
|
+
body: body,
|
44
|
+
uri: uri
|
45
|
+
})
|
46
|
+
end
|
47
|
+
|
22
48
|
new({
|
23
49
|
status: status,
|
24
50
|
version: "1.1",
|
25
51
|
headers: headers,
|
26
52
|
body: body,
|
27
|
-
|
53
|
+
request: request,
|
28
54
|
})
|
29
55
|
end
|
30
56
|
|
@@ -1,11 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HTTP
|
2
4
|
class Response
|
3
5
|
class Streamer
|
4
|
-
def initialize(str)
|
6
|
+
def initialize(str, encoding: Encoding::BINARY)
|
5
7
|
@io = StringIO.new str
|
8
|
+
@encoding = encoding
|
6
9
|
end
|
7
10
|
|
8
|
-
def readpartial(size = nil)
|
11
|
+
def readpartial(size = nil, outbuf = nil)
|
9
12
|
unless size
|
10
13
|
if defined?(HTTP::Client::BUFFER_SIZE)
|
11
14
|
size = HTTP::Client::BUFFER_SIZE
|
@@ -14,7 +17,12 @@ module HTTP
|
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
17
|
-
@io.read size
|
20
|
+
chunk = @io.read size, outbuf
|
21
|
+
chunk.force_encoding(@encoding) if chunk
|
22
|
+
end
|
23
|
+
|
24
|
+
def close
|
25
|
+
@io.close
|
18
26
|
end
|
19
27
|
|
20
28
|
def sequence_id
|
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HTTP
|
2
4
|
class WebMockPerform
|
3
|
-
def initialize(request, &perform)
|
5
|
+
def initialize(request, options, &perform)
|
4
6
|
@request = request
|
7
|
+
@options = options
|
5
8
|
@perform = perform
|
6
9
|
@request_signature = nil
|
7
10
|
end
|
@@ -38,12 +41,15 @@ module HTTP
|
|
38
41
|
webmock_response.raise_error_if_any
|
39
42
|
|
40
43
|
invoke_callbacks(webmock_response, real_request: false)
|
41
|
-
::HTTP::Response.from_webmock webmock_response, request_signature
|
44
|
+
response = ::HTTP::Response.from_webmock @request, webmock_response, request_signature
|
45
|
+
|
46
|
+
@options.features.each { |_name, feature| response = feature.wrap_response(response) }
|
47
|
+
response
|
42
48
|
end
|
43
49
|
|
44
50
|
def raise_timeout_error
|
45
51
|
raise Errno::ETIMEDOUT if HTTP::VERSION < "1.0.0"
|
46
|
-
raise HTTP::
|
52
|
+
raise HTTP::TimeoutError, "connection error: #{Errno::ETIMEDOUT.new}"
|
47
53
|
end
|
48
54
|
|
49
55
|
def perform
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'httpclient'
|
3
5
|
require 'jsonclient' # defined in 'httpclient' gem as well
|
@@ -43,6 +45,9 @@ if defined?(::HTTPClient)
|
|
43
45
|
end
|
44
46
|
|
45
47
|
module WebMockHTTPClients
|
48
|
+
|
49
|
+
REQUEST_RESPONSE_LOCK = Mutex.new
|
50
|
+
|
46
51
|
def do_get_block(req, proxy, conn, &block)
|
47
52
|
do_get(req, proxy, conn, false, &block)
|
48
53
|
end
|
@@ -57,7 +62,7 @@ if defined?(::HTTPClient)
|
|
57
62
|
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
58
63
|
|
59
64
|
if webmock_responses[request_signature]
|
60
|
-
webmock_response = webmock_responses.delete(request_signature)
|
65
|
+
webmock_response = synchronize_request_response { webmock_responses.delete(request_signature) }
|
61
66
|
response = build_httpclient_response(webmock_response, stream, req.header, &block)
|
62
67
|
@request_filter.each do |filter|
|
63
68
|
filter.filter_response(req, response)
|
@@ -68,15 +73,17 @@ if defined?(::HTTPClient)
|
|
68
73
|
res
|
69
74
|
elsif WebMock.net_connect_allowed?(request_signature.uri)
|
70
75
|
# in case there is a nil entry in the hash...
|
71
|
-
webmock_responses.delete(request_signature)
|
76
|
+
synchronize_request_response { webmock_responses.delete(request_signature) }
|
72
77
|
|
73
78
|
res = if stream
|
74
79
|
do_get_stream_without_webmock(req, proxy, conn, &block)
|
75
80
|
elsif block
|
76
81
|
body = ''
|
77
82
|
do_get_block_without_webmock(req, proxy, conn) do |http_res, chunk|
|
78
|
-
|
79
|
-
|
83
|
+
if chunk && chunk.bytesize > 0
|
84
|
+
body += chunk
|
85
|
+
block.call(http_res, chunk)
|
86
|
+
end
|
80
87
|
end
|
81
88
|
else
|
82
89
|
do_get_block_without_webmock(req, proxy, conn)
|
@@ -98,7 +105,7 @@ if defined?(::HTTPClient)
|
|
98
105
|
def do_request_async(method, uri, query, body, extheader)
|
99
106
|
req = create_request(method, uri, query, body, extheader)
|
100
107
|
request_signature = build_request_signature(req)
|
101
|
-
webmock_request_signatures << request_signature
|
108
|
+
synchronize_request_response { webmock_request_signatures << request_signature }
|
102
109
|
|
103
110
|
if webmock_responses[request_signature] || WebMock.net_connect_allowed?(request_signature.uri)
|
104
111
|
super
|
@@ -117,7 +124,7 @@ if defined?(::HTTPClient)
|
|
117
124
|
raise HTTPClient::TimeoutError if webmock_response.should_timeout
|
118
125
|
webmock_response.raise_error_if_any
|
119
126
|
|
120
|
-
block.call(response, body) if block
|
127
|
+
block.call(response, body) if block && body && body.bytesize > 0
|
121
128
|
|
122
129
|
response
|
123
130
|
end
|
@@ -182,7 +189,9 @@ if defined?(::HTTPClient)
|
|
182
189
|
|
183
190
|
def webmock_responses
|
184
191
|
@webmock_responses ||= Hash.new do |hash, request_signature|
|
185
|
-
|
192
|
+
synchronize_request_response do
|
193
|
+
hash[request_signature] = WebMock::StubRegistry.instance.response_for_request(request_signature)
|
194
|
+
end
|
186
195
|
end
|
187
196
|
end
|
188
197
|
|
@@ -191,8 +200,10 @@ if defined?(::HTTPClient)
|
|
191
200
|
end
|
192
201
|
|
193
202
|
def previous_signature_for(signature)
|
194
|
-
|
195
|
-
|
203
|
+
synchronize_request_response do
|
204
|
+
return nil unless index = webmock_request_signatures.index(signature)
|
205
|
+
webmock_request_signatures.delete_at(index)
|
206
|
+
end
|
196
207
|
end
|
197
208
|
|
198
209
|
private
|
@@ -207,6 +218,16 @@ if defined?(::HTTPClient)
|
|
207
218
|
hdrs
|
208
219
|
end
|
209
220
|
end
|
221
|
+
|
222
|
+
def synchronize_request_response
|
223
|
+
if REQUEST_RESPONSE_LOCK.owned?
|
224
|
+
yield
|
225
|
+
else
|
226
|
+
REQUEST_RESPONSE_LOCK.synchronize do
|
227
|
+
yield
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
210
231
|
end
|
211
232
|
|
212
233
|
class WebMockHTTPClient < HTTPClient
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'manticore'
|
3
5
|
rescue LoadError
|
@@ -24,6 +26,12 @@ if defined?(Manticore)
|
|
24
26
|
Manticore.instance_variable_set(:@manticore_facade, OriginalManticoreClient.new)
|
25
27
|
end
|
26
28
|
|
29
|
+
class StubbedTimeoutResponse < Manticore::StubbedResponse
|
30
|
+
def call
|
31
|
+
@handlers[:failure].call(Manticore::ConnectTimeout.new("Too slow (mocked timeout)"))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
27
35
|
class WebMockManticoreClient < Manticore::Client
|
28
36
|
def request(klass, url, options={}, &block)
|
29
37
|
super(klass, WebMock::Util::URI.normalize_uri(url).to_s, format_options(options))
|
@@ -50,19 +58,22 @@ if defined?(Manticore)
|
|
50
58
|
|
51
59
|
if webmock_response = registered_response_for(request_signature)
|
52
60
|
webmock_response.raise_error_if_any
|
53
|
-
manticore_response = generate_manticore_response(webmock_response)
|
54
|
-
|
61
|
+
manticore_response = generate_manticore_response(webmock_response)
|
62
|
+
manticore_response.on_success do
|
63
|
+
WebMock::CallbackRegistry.invoke_callbacks({lib: :manticore, real_request: false}, request_signature, webmock_response)
|
64
|
+
end
|
55
65
|
|
56
66
|
elsif real_request_allowed?(request_signature.uri)
|
57
|
-
manticore_response = Manticore::Response.new(self, request, context, &block)
|
58
|
-
|
59
|
-
|
67
|
+
manticore_response = Manticore::Response.new(self, request, context, &block)
|
68
|
+
manticore_response.on_complete do |completed_response|
|
69
|
+
webmock_response = generate_webmock_response(completed_response)
|
70
|
+
WebMock::CallbackRegistry.invoke_callbacks({lib: :manticore, real_request: true}, request_signature, webmock_response)
|
71
|
+
end
|
60
72
|
|
61
73
|
else
|
62
74
|
raise WebMock::NetConnectNotAllowedError.new(request_signature)
|
63
75
|
end
|
64
76
|
|
65
|
-
WebMock::CallbackRegistry.invoke_callbacks({lib: :manticore, real_request: real_request}, request_signature, webmock_response)
|
66
77
|
manticore_response
|
67
78
|
end
|
68
79
|
|
@@ -103,21 +114,30 @@ if defined?(Manticore)
|
|
103
114
|
end
|
104
115
|
|
105
116
|
def generate_manticore_response(webmock_response)
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
117
|
+
if webmock_response.should_timeout
|
118
|
+
StubbedTimeoutResponse.new
|
119
|
+
else
|
120
|
+
Manticore::StubbedResponse.stub(
|
121
|
+
code: webmock_response.status[0],
|
122
|
+
body: webmock_response.body,
|
123
|
+
headers: webmock_response.headers,
|
124
|
+
cookies: {}
|
125
|
+
)
|
126
|
+
end
|
114
127
|
end
|
115
128
|
|
116
129
|
def generate_webmock_response(manticore_response)
|
117
130
|
webmock_response = WebMock::Response.new
|
118
131
|
webmock_response.status = [manticore_response.code, manticore_response.message]
|
119
|
-
webmock_response.body = manticore_response.body
|
120
132
|
webmock_response.headers = manticore_response.headers
|
133
|
+
|
134
|
+
# The attempt to read the body could fail if manticore is used in a streaming mode
|
135
|
+
webmock_response.body = begin
|
136
|
+
manticore_response.body
|
137
|
+
rescue ::Manticore::StreamClosedException
|
138
|
+
nil
|
139
|
+
end
|
140
|
+
|
121
141
|
webmock_response
|
122
142
|
end
|
123
143
|
end
|