webmock 3.14.0 → 3.25.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +213 -3
- data/README.md +66 -20
- data/lib/webmock/api.rb +2 -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 +16 -4
- data/lib/webmock/http_lib_adapters/curb_adapter.rb +4 -2
- data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +17 -7
- data/lib/webmock/http_lib_adapters/excon_adapter.rb +2 -0
- 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 +3 -3
- data/lib/webmock/http_lib_adapters/http_rb/request.rb +17 -5
- data/lib/webmock/http_lib_adapters/http_rb/response.rb +32 -9
- data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +10 -2
- data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +8 -2
- data/lib/webmock/http_lib_adapters/http_rb_adapter.rb +7 -5
- data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +26 -25
- data/lib/webmock/http_lib_adapters/manticore_adapter.rb +2 -0
- data/lib/webmock/http_lib_adapters/net_http.rb +46 -121
- data/lib/webmock/http_lib_adapters/net_http_response.rb +2 -0
- data/lib/webmock/http_lib_adapters/patron_adapter.rb +3 -1
- data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +18 -2
- data/lib/webmock/matchers/any_arg_matcher.rb +2 -0
- data/lib/webmock/matchers/hash_argument_matcher.rb +2 -0
- data/lib/webmock/matchers/hash_excluding_matcher.rb +2 -0
- data/lib/webmock/matchers/hash_including_matcher.rb +2 -0
- data/lib/webmock/minitest.rb +2 -0
- data/lib/webmock/rack_response.rb +5 -1
- data/lib/webmock/request_body_diff.rb +2 -0
- data/lib/webmock/request_execution_verifier.rb +2 -0
- data/lib/webmock/request_pattern.rb +35 -12
- data/lib/webmock/request_registry.rb +2 -0
- data/lib/webmock/request_signature.rb +4 -2
- data/lib/webmock/request_signature_snippet.rb +2 -0
- data/lib/webmock/request_stub.rb +34 -0
- data/lib/webmock/response.rb +15 -13
- 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 +2 -0
- data/lib/webmock/stub_registry.rb +2 -0
- data/lib/webmock/stub_request_snippet.rb +2 -0
- data/lib/webmock/test_unit.rb +2 -0
- data/lib/webmock/util/hash_counter.rb +12 -6
- 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 +23 -10
- data/lib/webmock/util/parsers/json.rb +72 -0
- data/lib/webmock/util/parsers/parse_error.rb +7 -0
- data/lib/webmock/util/parsers/xml.rb +16 -0
- data/lib/webmock/util/query_mapper.rb +2 -0
- data/lib/webmock/util/uri.rb +3 -1
- data/lib/webmock/util/values_stringifier.rb +2 -0
- data/lib/webmock/util/version_checker.rb +7 -5
- data/lib/webmock/version.rb +3 -1
- data/lib/webmock/webmock.rb +12 -0
- data/lib/webmock.rb +4 -2
- metadata +66 -185
- data/.gemtest +0 -0
- data/.github/workflows/CI.yml +0 -37
- data/.gitignore +0 -34
- data/.rspec-tm +0 -2
- data/Gemfile +0 -9
- data/Rakefile +0 -38
- data/lib/webmock/util/json.rb +0 -67
- data/minitest/test_helper.rb +0 -34
- data/minitest/test_webmock.rb +0 -9
- data/minitest/webmock_spec.rb +0 -60
- data/spec/acceptance/async_http_client/async_http_client_spec.rb +0 -375
- data/spec/acceptance/async_http_client/async_http_client_spec_helper.rb +0 -73
- data/spec/acceptance/curb/curb_spec.rb +0 -499
- data/spec/acceptance/curb/curb_spec_helper.rb +0 -147
- data/spec/acceptance/em_http_request/em_http_request_spec.rb +0 -462
- data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +0 -77
- data/spec/acceptance/excon/excon_spec.rb +0 -77
- data/spec/acceptance/excon/excon_spec_helper.rb +0 -52
- data/spec/acceptance/http_rb/http_rb_spec.rb +0 -93
- data/spec/acceptance/http_rb/http_rb_spec_helper.rb +0 -54
- data/spec/acceptance/httpclient/httpclient_spec.rb +0 -217
- data/spec/acceptance/httpclient/httpclient_spec_helper.rb +0 -57
- data/spec/acceptance/manticore/manticore_spec.rb +0 -107
- 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 -369
- 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 -125
- 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 -148
- 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 -930
- data/spec/acceptance/shared/returning_declared_responses.rb +0 -409
- data/spec/acceptance/shared/stubbing_requests.rb +0 -678
- 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 -70
- data/spec/unit/api_spec.rb +0 -175
- 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_excluding_matcher_spec.rb +0 -61
- 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 -736
- 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 -286
- data/spec/unit/stub_registry_spec.rb +0 -103
- data/spec/unit/stub_request_snippet_spec.rb +0 -115
- 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 -157
- data/spec/unit/util/uri_spec.rb +0 -371
- data/spec/unit/util/version_checker_spec.rb +0 -65
- data/spec/unit/webmock_spec.rb +0 -60
- data/test/http_request.rb +0 -24
- data/test/shared_test.rb +0 -108
- data/test/test_helper.rb +0 -23
- data/test/test_webmock.rb +0 -12
- data/webmock.gemspec +0 -54
@@ -1,12 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HTTP
|
2
4
|
class Response
|
3
5
|
def to_webmock
|
4
6
|
webmock_response = ::WebMock::Response.new
|
5
7
|
|
6
8
|
webmock_response.status = [status.to_i, reason]
|
9
|
+
|
7
10
|
webmock_response.body = body.to_s
|
8
|
-
|
11
|
+
# This call is used to reset the body of the response to enable it to be streamed if necessary.
|
12
|
+
# The `body.to_s` call above reads the body, which allows WebMock to trigger any registered callbacks.
|
13
|
+
# However, once the body is read to_s, it cannot be streamed again and attempting to do so
|
14
|
+
# will raise a "HTTP::StateError: body has already been consumed" error.
|
15
|
+
# To avoid this error, we replace the original body with a new one.
|
16
|
+
# The new body has its @stream attribute set to new Streamer, instead of the original Connection.
|
17
|
+
# Unfortunately, it's not possible to reset the original body to its initial streaming state.
|
18
|
+
# Therefore, this replacement is the best workaround currently available.
|
19
|
+
reset_body_to_allow_it_to_be_streamed!(webmock_response)
|
9
20
|
|
21
|
+
webmock_response.headers = headers.to_h
|
10
22
|
webmock_response
|
11
23
|
end
|
12
24
|
|
@@ -19,13 +31,7 @@ module HTTP
|
|
19
31
|
# HTTP.rb 3.0+ uses a keyword argument to pass the encoding, but 1.x
|
20
32
|
# and 2.x use a positional argument, and 0.x don't support supplying
|
21
33
|
# the encoding.
|
22
|
-
body =
|
23
|
-
Body.new(Streamer.new(webmock_response.body))
|
24
|
-
elsif HTTP::VERSION < "3.0.0"
|
25
|
-
Body.new(Streamer.new(webmock_response.body), webmock_response.body.encoding)
|
26
|
-
else
|
27
|
-
Body.new(Streamer.new(webmock_response.body), encoding: webmock_response.body.encoding)
|
28
|
-
end
|
34
|
+
body = build_http_rb_response_body_from_webmock_response(webmock_response)
|
29
35
|
|
30
36
|
return new(status, "1.1", headers, body, uri) if HTTP::VERSION < "1.0.0"
|
31
37
|
|
@@ -49,7 +55,18 @@ module HTTP
|
|
49
55
|
})
|
50
56
|
end
|
51
57
|
|
52
|
-
|
58
|
+
def build_http_rb_response_body_from_webmock_response(webmock_response)
|
59
|
+
if HTTP::VERSION < "1.0.0"
|
60
|
+
Body.new(Streamer.new(webmock_response.body))
|
61
|
+
elsif HTTP::VERSION < "3.0.0"
|
62
|
+
Body.new(Streamer.new(webmock_response.body), webmock_response.body.encoding)
|
63
|
+
else
|
64
|
+
Body.new(
|
65
|
+
Streamer.new(webmock_response.body, encoding: webmock_response.body.encoding),
|
66
|
+
encoding: webmock_response.body.encoding
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
53
70
|
|
54
71
|
def normalize_uri(uri)
|
55
72
|
return unless uri
|
@@ -60,5 +77,11 @@ module HTTP
|
|
60
77
|
uri
|
61
78
|
end
|
62
79
|
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def reset_body_to_allow_it_to_be_streamed!(webmock_response)
|
84
|
+
@body = self.class.build_http_rb_response_body_from_webmock_response(webmock_response)
|
85
|
+
end
|
63
86
|
end
|
64
87
|
end
|
@@ -1,8 +1,11 @@
|
|
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
11
|
def readpartial(size = nil, outbuf = nil)
|
@@ -14,13 +17,18 @@ module HTTP
|
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
17
|
-
@io.read size, outbuf
|
20
|
+
chunk = @io.read size, outbuf
|
21
|
+
chunk.force_encoding(@encoding) if chunk
|
18
22
|
end
|
19
23
|
|
20
24
|
def close
|
21
25
|
@io.close
|
22
26
|
end
|
23
27
|
|
28
|
+
def finished_request?
|
29
|
+
@io.eof?
|
30
|
+
end
|
31
|
+
|
24
32
|
def sequence_id
|
25
33
|
-1
|
26
34
|
end
|
@@ -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,7 +41,10 @@ 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 @request, 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
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require "http"
|
3
5
|
rescue LoadError
|
@@ -29,9 +31,9 @@ if defined?(HTTP) && defined?(HTTP::VERSION)
|
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
require_relative "http_rb/client"
|
35
|
+
require_relative "http_rb/request"
|
36
|
+
require_relative "http_rb/response"
|
37
|
+
require_relative "http_rb/streamer"
|
38
|
+
require_relative "http_rb/webmock"
|
37
39
|
end
|
@@ -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,8 @@ if defined?(::HTTPClient)
|
|
43
45
|
end
|
44
46
|
|
45
47
|
module WebMockHTTPClients
|
48
|
+
WEBMOCK_HTTPCLIENT_RESPONSES = :webmock_httpclient_responses
|
49
|
+
WEBMOCK_HTTPCLIENT_REQUEST_SIGNATURES = :webmock_httpclient_request_signatures
|
46
50
|
|
47
51
|
REQUEST_RESPONSE_LOCK = Mutex.new
|
48
52
|
|
@@ -55,12 +59,14 @@ if defined?(::HTTPClient)
|
|
55
59
|
end
|
56
60
|
|
57
61
|
def do_get(req, proxy, conn, stream = false, &block)
|
62
|
+
clear_thread_variables unless conn.async_thread
|
63
|
+
|
58
64
|
request_signature = build_request_signature(req, :reuse_existing)
|
59
65
|
|
60
66
|
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
61
67
|
|
62
68
|
if webmock_responses[request_signature]
|
63
|
-
webmock_response =
|
69
|
+
webmock_response = webmock_responses.delete(request_signature)
|
64
70
|
response = build_httpclient_response(webmock_response, stream, req.header, &block)
|
65
71
|
@request_filter.each do |filter|
|
66
72
|
filter.filter_response(req, response)
|
@@ -71,7 +77,7 @@ if defined?(::HTTPClient)
|
|
71
77
|
res
|
72
78
|
elsif WebMock.net_connect_allowed?(request_signature.uri)
|
73
79
|
# in case there is a nil entry in the hash...
|
74
|
-
|
80
|
+
webmock_responses.delete(request_signature)
|
75
81
|
|
76
82
|
res = if stream
|
77
83
|
do_get_stream_without_webmock(req, proxy, conn, &block)
|
@@ -101,12 +107,16 @@ if defined?(::HTTPClient)
|
|
101
107
|
end
|
102
108
|
|
103
109
|
def do_request_async(method, uri, query, body, extheader)
|
110
|
+
clear_thread_variables
|
104
111
|
req = create_request(method, uri, query, body, extheader)
|
105
112
|
request_signature = build_request_signature(req)
|
106
|
-
|
113
|
+
webmock_request_signatures << request_signature
|
107
114
|
|
108
115
|
if webmock_responses[request_signature] || WebMock.net_connect_allowed?(request_signature.uri)
|
109
|
-
super
|
116
|
+
conn = super
|
117
|
+
conn.async_thread[WEBMOCK_HTTPCLIENT_REQUEST_SIGNATURES] = Thread.current[WEBMOCK_HTTPCLIENT_REQUEST_SIGNATURES]
|
118
|
+
conn.async_thread[WEBMOCK_HTTPCLIENT_RESPONSES] = Thread.current[WEBMOCK_HTTPCLIENT_RESPONSES]
|
119
|
+
conn
|
110
120
|
else
|
111
121
|
raise WebMock::NetConnectNotAllowedError.new(request_signature)
|
112
122
|
end
|
@@ -155,14 +165,14 @@ if defined?(::HTTPClient)
|
|
155
165
|
end
|
156
166
|
|
157
167
|
def build_request_signature(req, reuse_existing = false)
|
158
|
-
uri = WebMock::Util::URI.heuristic_parse(req.header.request_uri.to_s)
|
159
|
-
uri.query = WebMock::Util::QueryMapper.values_to_query(req.header.request_query, notation: WebMock::Config.instance.query_values_notation) if req.header.request_query
|
160
|
-
uri.port = req.header.request_uri.port
|
161
|
-
|
162
168
|
@request_filter.each do |filter|
|
163
169
|
filter.filter_request(req)
|
164
170
|
end
|
165
171
|
|
172
|
+
uri = WebMock::Util::URI.heuristic_parse(req.header.request_uri.to_s)
|
173
|
+
uri.query = WebMock::Util::QueryMapper.values_to_query(req.header.request_query, notation: WebMock::Config.instance.query_values_notation) if req.header.request_query
|
174
|
+
uri.port = req.header.request_uri.port
|
175
|
+
|
166
176
|
headers = req.header.all.inject({}) do |hdrs, header|
|
167
177
|
hdrs[header[0]] ||= []
|
168
178
|
hdrs[header[0]] << header[1]
|
@@ -186,22 +196,18 @@ if defined?(::HTTPClient)
|
|
186
196
|
end
|
187
197
|
|
188
198
|
def webmock_responses
|
189
|
-
|
190
|
-
|
191
|
-
hash[request_signature] = WebMock::StubRegistry.instance.response_for_request(request_signature)
|
192
|
-
end
|
199
|
+
Thread.current[WEBMOCK_HTTPCLIENT_RESPONSES] ||= Hash.new do |hash, request_signature|
|
200
|
+
hash[request_signature] = WebMock::StubRegistry.instance.response_for_request(request_signature)
|
193
201
|
end
|
194
202
|
end
|
195
203
|
|
196
204
|
def webmock_request_signatures
|
197
|
-
|
205
|
+
Thread.current[WEBMOCK_HTTPCLIENT_REQUEST_SIGNATURES] ||= []
|
198
206
|
end
|
199
207
|
|
200
208
|
def previous_signature_for(signature)
|
201
|
-
|
202
|
-
|
203
|
-
webmock_request_signatures.delete_at(index)
|
204
|
-
end
|
209
|
+
return nil unless index = webmock_request_signatures.index(signature)
|
210
|
+
webmock_request_signatures.delete_at(index)
|
205
211
|
end
|
206
212
|
|
207
213
|
private
|
@@ -217,14 +223,9 @@ if defined?(::HTTPClient)
|
|
217
223
|
end
|
218
224
|
end
|
219
225
|
|
220
|
-
def
|
221
|
-
|
222
|
-
|
223
|
-
else
|
224
|
-
REQUEST_RESPONSE_LOCK.synchronize do
|
225
|
-
yield
|
226
|
-
end
|
227
|
-
end
|
226
|
+
def clear_thread_variables
|
227
|
+
Thread.current[WEBMOCK_HTTPCLIENT_REQUEST_SIGNATURES] = nil
|
228
|
+
Thread.current[WEBMOCK_HTTPCLIENT_RESPONSES] = nil
|
228
229
|
end
|
229
230
|
end
|
230
231
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'net/http'
|
2
4
|
require 'net/https'
|
3
5
|
require 'stringio'
|
@@ -10,24 +12,25 @@ module WebMock
|
|
10
12
|
adapter_for :net_http
|
11
13
|
|
12
14
|
OriginalNetHTTP = Net::HTTP unless const_defined?(:OriginalNetHTTP)
|
13
|
-
|
15
|
+
# This will be removed in Ruby 3.5. In Ruby 3.4, const_remove will warn.
|
16
|
+
HAS_LEGACY_CONSTANT = Net.const_defined?(:HTTPSession)
|
14
17
|
|
15
18
|
def self.enable!
|
16
|
-
Net.send(:remove_const, :BufferedIO)
|
17
19
|
Net.send(:remove_const, :HTTP)
|
18
|
-
Net.send(:remove_const, :HTTPSession)
|
19
20
|
Net.send(:const_set, :HTTP, @webMockNetHTTP)
|
20
|
-
|
21
|
-
|
21
|
+
if HAS_LEGACY_CONSTANT
|
22
|
+
remove_silently(Net, :HTTPSession)
|
23
|
+
Net.send(:const_set, :HTTPSession, @webMockNetHTTP)
|
24
|
+
end
|
22
25
|
end
|
23
26
|
|
24
27
|
def self.disable!
|
25
|
-
Net.send(:remove_const, :BufferedIO)
|
26
28
|
Net.send(:remove_const, :HTTP)
|
27
|
-
Net.send(:remove_const, :HTTPSession)
|
28
29
|
Net.send(:const_set, :HTTP, OriginalNetHTTP)
|
29
|
-
|
30
|
-
|
30
|
+
if HAS_LEGACY_CONSTANT
|
31
|
+
remove_silently(Net, :HTTPSession)
|
32
|
+
Net.send(:const_set, :HTTPSession, OriginalNetHTTP)
|
33
|
+
end
|
31
34
|
|
32
35
|
#copy all constants from @webMockNetHTTP to original Net::HTTP
|
33
36
|
#in case any constants were added to @webMockNetHTTP instead of Net::HTTP
|
@@ -40,6 +43,14 @@ module WebMock
|
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
46
|
+
def self.remove_silently(mod, const) #:nodoc:
|
47
|
+
# Don't warn on removing the deprecated constant
|
48
|
+
verbose, $VERBOSE = $VERBOSE, nil
|
49
|
+
mod.send(:remove_const, const)
|
50
|
+
ensure
|
51
|
+
$VERBOSE = verbose
|
52
|
+
end
|
53
|
+
|
43
54
|
@webMockNetHTTP = Class.new(Net::HTTP) do
|
44
55
|
class << self
|
45
56
|
def socket_type
|
@@ -80,7 +91,7 @@ module WebMock
|
|
80
91
|
@socket = Net::HTTP.socket_type.new
|
81
92
|
WebMock::CallbackRegistry.invoke_callbacks(
|
82
93
|
{lib: :net_http}, request_signature, webmock_response)
|
83
|
-
build_net_http_response(webmock_response, &block)
|
94
|
+
build_net_http_response(webmock_response, request.uri, &block)
|
84
95
|
elsif WebMock.net_connect_allowed?(request_signature.uri)
|
85
96
|
check_right_http_connection
|
86
97
|
after_request = lambda do |response|
|
@@ -98,13 +109,8 @@ module WebMock
|
|
98
109
|
after_request.call(response)
|
99
110
|
}
|
100
111
|
if started?
|
101
|
-
|
102
|
-
|
103
|
-
else
|
104
|
-
start_with_connect_without_finish {
|
105
|
-
super_with_after_request.call
|
106
|
-
}
|
107
|
-
end
|
112
|
+
ensure_actual_connection
|
113
|
+
super_with_after_request.call
|
108
114
|
else
|
109
115
|
start_with_connect {
|
110
116
|
super_with_after_request.call
|
@@ -119,39 +125,40 @@ module WebMock
|
|
119
125
|
raise IOError, 'HTTP session already opened' if @started
|
120
126
|
if block_given?
|
121
127
|
begin
|
128
|
+
@socket = Net::HTTP.socket_type.new
|
122
129
|
@started = true
|
123
130
|
return yield(self)
|
124
131
|
ensure
|
125
132
|
do_finish
|
126
133
|
end
|
127
134
|
end
|
135
|
+
@socket = Net::HTTP.socket_type.new
|
128
136
|
@started = true
|
129
137
|
self
|
130
138
|
end
|
131
139
|
|
132
140
|
|
133
|
-
def
|
134
|
-
if
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
end
|
141
|
+
def ensure_actual_connection
|
142
|
+
if @socket.is_a?(StubSocket)
|
143
|
+
@socket&.close
|
144
|
+
@socket = nil
|
145
|
+
do_start
|
139
146
|
end
|
140
|
-
do_start
|
141
|
-
self
|
142
147
|
end
|
143
148
|
|
144
149
|
alias_method :start_with_connect, :start
|
145
150
|
|
146
151
|
def start(&block)
|
147
|
-
|
152
|
+
uri = Addressable::URI.parse(WebMock::NetHTTPUtility.get_uri(self))
|
153
|
+
|
154
|
+
if WebMock.net_http_connect_on_start?(uri)
|
148
155
|
super(&block)
|
149
156
|
else
|
150
157
|
start_without_connect(&block)
|
151
158
|
end
|
152
159
|
end
|
153
160
|
|
154
|
-
def build_net_http_response(webmock_response, &block)
|
161
|
+
def build_net_http_response(webmock_response, request_uri, &block)
|
155
162
|
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])
|
156
163
|
body = webmock_response.body
|
157
164
|
body = nil if webmock_response.status[0].to_s == '204'
|
@@ -166,10 +173,12 @@ module WebMock
|
|
166
173
|
|
167
174
|
response.instance_variable_set(:@read, true)
|
168
175
|
|
176
|
+
response.uri = request_uri
|
177
|
+
|
169
178
|
response.extend Net::WebMockHTTPResponse
|
170
179
|
|
171
180
|
if webmock_response.should_timeout
|
172
|
-
raise
|
181
|
+
raise Net::OpenTimeout, "execution expired"
|
173
182
|
end
|
174
183
|
|
175
184
|
webmock_response.raise_error_if_any
|
@@ -179,16 +188,6 @@ module WebMock
|
|
179
188
|
response
|
180
189
|
end
|
181
190
|
|
182
|
-
def timeout_exception
|
183
|
-
if defined?(Net::OpenTimeout)
|
184
|
-
# Ruby 2.x
|
185
|
-
Net::OpenTimeout
|
186
|
-
else
|
187
|
-
# Fallback, if things change
|
188
|
-
Timeout::Error
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
191
|
def build_webmock_response(net_http_response)
|
193
192
|
webmock_response = WebMock::Response.new
|
194
193
|
webmock_response.status = [
|
@@ -222,31 +221,21 @@ module WebMock
|
|
222
221
|
end
|
223
222
|
end
|
224
223
|
|
225
|
-
# patch for StringIO behavior in Ruby 2.2.3
|
226
|
-
# https://github.com/bblimke/webmock/issues/558
|
227
|
-
class PatchedStringIO < StringIO #:nodoc:
|
228
|
-
|
229
|
-
alias_method :orig_read_nonblock, :read_nonblock
|
230
|
-
|
231
|
-
def read_nonblock(size, *args, **kwargs)
|
232
|
-
args.reject! {|arg| !arg.is_a?(Hash)}
|
233
|
-
orig_read_nonblock(size, *args, **kwargs)
|
234
|
-
end
|
235
|
-
|
236
|
-
end
|
237
|
-
|
238
224
|
class StubSocket #:nodoc:
|
239
225
|
|
240
226
|
attr_accessor :read_timeout, :continue_timeout, :write_timeout
|
241
227
|
|
242
228
|
def initialize(*args)
|
229
|
+
@closed = false
|
243
230
|
end
|
244
231
|
|
245
232
|
def closed?
|
246
|
-
@closed
|
233
|
+
@closed
|
247
234
|
end
|
248
235
|
|
249
236
|
def close
|
237
|
+
@closed = true
|
238
|
+
nil
|
250
239
|
end
|
251
240
|
|
252
241
|
def readuntil(*args)
|
@@ -258,57 +247,13 @@ class StubSocket #:nodoc:
|
|
258
247
|
|
259
248
|
class StubIO
|
260
249
|
def setsockopt(*args); end
|
250
|
+
def peer_cert; end
|
251
|
+
def peeraddr; ["AF_INET", 443, "127.0.0.1", "127.0.0.1"] end
|
252
|
+
def ssl_version; "TLSv1.3" end
|
253
|
+
def cipher; ["TLS_AES_128_GCM_SHA256", "TLSv1.3", 128, 128] end
|
261
254
|
end
|
262
255
|
end
|
263
256
|
|
264
|
-
module Net #:nodoc: all
|
265
|
-
|
266
|
-
class WebMockNetBufferedIO < BufferedIO
|
267
|
-
def initialize(io, *args, **kwargs)
|
268
|
-
io = case io
|
269
|
-
when Socket, OpenSSL::SSL::SSLSocket, IO
|
270
|
-
io
|
271
|
-
when StringIO
|
272
|
-
PatchedStringIO.new(io.string)
|
273
|
-
when String
|
274
|
-
PatchedStringIO.new(io)
|
275
|
-
end
|
276
|
-
raise "Unable to create local socket" unless io
|
277
|
-
|
278
|
-
# Prior to 2.4.0 `BufferedIO` only takes a single argument (`io`) with no
|
279
|
-
# options. Here we pass through our full set of arguments only if we're
|
280
|
-
# on 2.4.0 or later, and use a simplified invocation otherwise.
|
281
|
-
if RUBY_VERSION >= '2.4.0'
|
282
|
-
super
|
283
|
-
else
|
284
|
-
super(io)
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
if RUBY_VERSION >= '2.6.0'
|
289
|
-
# https://github.com/ruby/ruby/blob/7d02441f0d6e5c9d0a73a024519eba4f69e36dce/lib/net/protocol.rb#L208
|
290
|
-
# Modified version of method from ruby, so that nil is always passed into orig_read_nonblock to avoid timeout
|
291
|
-
def rbuf_fill
|
292
|
-
case rv = @io.read_nonblock(BUFSIZE, nil, exception: false)
|
293
|
-
when String
|
294
|
-
return if rv.nil?
|
295
|
-
@rbuf << rv
|
296
|
-
rv.clear
|
297
|
-
return
|
298
|
-
when :wait_readable
|
299
|
-
@io.to_io.wait_readable(@read_timeout) or raise Net::ReadTimeout
|
300
|
-
when :wait_writable
|
301
|
-
@io.to_io.wait_writable(@read_timeout) or raise Net::ReadTimeout
|
302
|
-
when nil
|
303
|
-
raise EOFError, 'end of file reached'
|
304
|
-
end while true
|
305
|
-
end
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
end
|
310
|
-
|
311
|
-
|
312
257
|
module WebMock
|
313
258
|
module NetHTTPUtility
|
314
259
|
|
@@ -325,7 +270,6 @@ module WebMock
|
|
325
270
|
method = request.method.downcase.to_sym
|
326
271
|
|
327
272
|
headers = Hash[*request.to_hash.map {|k,v| [k, v]}.inject([]) {|r,x| r + x}]
|
328
|
-
validate_headers(headers)
|
329
273
|
|
330
274
|
if request.body_stream
|
331
275
|
body = request.body_stream.read
|
@@ -341,7 +285,7 @@ module WebMock
|
|
341
285
|
WebMock::RequestSignature.new(method, uri, body: request.body, headers: headers)
|
342
286
|
end
|
343
287
|
|
344
|
-
def self.get_uri(net_http, path)
|
288
|
+
def self.get_uri(net_http, path = nil)
|
345
289
|
protocol = net_http.use_ssl? ? "https" : "http"
|
346
290
|
|
347
291
|
hostname = net_http.address
|
@@ -350,25 +294,6 @@ module WebMock
|
|
350
294
|
"#{protocol}://#{hostname}:#{net_http.port}#{path}"
|
351
295
|
end
|
352
296
|
|
353
|
-
def self.validate_headers(headers)
|
354
|
-
# For Ruby versions < 2.3.0, if you make a request with headers that are symbols
|
355
|
-
# Net::HTTP raises a NoMethodError
|
356
|
-
#
|
357
|
-
# WebMock normalizes headers when creating a RequestSignature,
|
358
|
-
# and will update all headers from symbols to strings.
|
359
|
-
#
|
360
|
-
# This could create a false positive in a test suite with WebMock.
|
361
|
-
#
|
362
|
-
# So before this point, WebMock raises an ArgumentError if any of the headers are symbols
|
363
|
-
# instead of the cryptic NoMethodError "undefined method `split' ...` from Net::HTTP
|
364
|
-
if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.3.0')
|
365
|
-
header_as_symbol = headers.keys.find {|header| header.is_a? Symbol}
|
366
|
-
if header_as_symbol
|
367
|
-
raise ArgumentError.new("Net:HTTP does not accept headers as symbols")
|
368
|
-
end
|
369
|
-
end
|
370
|
-
end
|
371
|
-
|
372
297
|
def self.check_right_http_connection
|
373
298
|
@was_right_http_connection_loaded = defined?(RightHttpConnection)
|
374
299
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'patron'
|
3
5
|
rescue LoadError
|
4
6
|
# patron not found
|
5
7
|
end
|
6
8
|
|
7
|
-
if defined?(::Patron)
|
9
|
+
if defined?(::Patron::Session)
|
8
10
|
module WebMock
|
9
11
|
module HttpLibAdapters
|
10
12
|
class PatronAdapter < ::WebMock::HttpLibAdapter
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'typhoeus'
|
3
5
|
rescue LoadError
|
@@ -94,7 +96,14 @@ if defined?(Typhoeus)
|
|
94
96
|
status_message: "",
|
95
97
|
body: "",
|
96
98
|
headers: {},
|
97
|
-
return_code: :operation_timedout
|
99
|
+
return_code: :operation_timedout,
|
100
|
+
total_time: 0.0,
|
101
|
+
starttransfer_time: 0.0,
|
102
|
+
appconnect_time: 0.0,
|
103
|
+
pretransfer_time: 0.0,
|
104
|
+
connect_time: 0.0,
|
105
|
+
namelookup_time: 0.0,
|
106
|
+
redirect_time: 0.0
|
98
107
|
)
|
99
108
|
else
|
100
109
|
::Typhoeus::Response.new(
|
@@ -102,7 +111,14 @@ if defined?(Typhoeus)
|
|
102
111
|
status_message: webmock_response.status[1],
|
103
112
|
body: webmock_response.body,
|
104
113
|
headers: webmock_response.headers,
|
105
|
-
effective_url: request_signature.uri
|
114
|
+
effective_url: request_signature.uri,
|
115
|
+
total_time: 0.0,
|
116
|
+
starttransfer_time: 0.0,
|
117
|
+
appconnect_time: 0.0,
|
118
|
+
pretransfer_time: 0.0,
|
119
|
+
connect_time: 0.0,
|
120
|
+
namelookup_time: 0.0,
|
121
|
+
redirect_time: 0.0
|
106
122
|
)
|
107
123
|
end
|
108
124
|
response.mock = :webmock
|