webmock 3.6.2 → 3.14.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/CI.yml +37 -0
  3. data/CHANGELOG.md +214 -0
  4. data/Gemfile +1 -1
  5. data/README.md +85 -32
  6. data/Rakefile +12 -2
  7. data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +216 -0
  8. data/lib/webmock/http_lib_adapters/curb_adapter.rb +4 -0
  9. data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +7 -4
  10. data/lib/webmock/http_lib_adapters/excon_adapter.rb +3 -0
  11. data/lib/webmock/http_lib_adapters/http_rb/client.rb +4 -1
  12. data/lib/webmock/http_lib_adapters/http_rb/response.rb +24 -3
  13. data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +2 -2
  14. data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +1 -1
  15. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +23 -6
  16. data/lib/webmock/http_lib_adapters/manticore_adapter.rb +24 -9
  17. data/lib/webmock/http_lib_adapters/net_http.rb +43 -19
  18. data/lib/webmock/request_pattern.rb +82 -47
  19. data/lib/webmock/response.rb +11 -5
  20. data/lib/webmock/rspec.rb +2 -1
  21. data/lib/webmock/stub_registry.rb +26 -11
  22. data/lib/webmock/test_unit.rb +1 -3
  23. data/lib/webmock/util/uri.rb +5 -4
  24. data/lib/webmock/version.rb +1 -1
  25. data/lib/webmock/webmock.rb +5 -3
  26. data/lib/webmock.rb +1 -0
  27. data/spec/acceptance/async_http_client/async_http_client_spec.rb +375 -0
  28. data/spec/acceptance/async_http_client/async_http_client_spec_helper.rb +73 -0
  29. data/spec/acceptance/curb/curb_spec.rb +12 -5
  30. data/spec/acceptance/em_http_request/em_http_request_spec.rb +56 -0
  31. data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +1 -1
  32. data/spec/acceptance/excon/excon_spec_helper.rb +2 -0
  33. data/spec/acceptance/http_rb/http_rb_spec.rb +11 -0
  34. data/spec/acceptance/manticore/manticore_spec.rb +51 -0
  35. data/spec/acceptance/net_http/net_http_spec.rb +38 -0
  36. data/spec/acceptance/patron/patron_spec_helper.rb +2 -2
  37. data/spec/acceptance/shared/callbacks.rb +2 -1
  38. data/spec/acceptance/shared/returning_declared_responses.rb +36 -15
  39. data/spec/acceptance/shared/stubbing_requests.rb +35 -0
  40. data/spec/unit/request_pattern_spec.rb +183 -48
  41. data/spec/unit/response_spec.rb +22 -18
  42. data/spec/unit/util/uri_spec.rb +10 -0
  43. data/spec/unit/webmock_spec.rb +52 -11
  44. data/test/test_webmock.rb +6 -0
  45. data/webmock.gemspec +11 -1
  46. metadata +48 -10
  47. data/.travis.yml +0 -19
@@ -0,0 +1,375 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'acceptance/webmock_shared'
4
+ require_relative './async_http_client_spec_helper'
5
+
6
+ require 'protocol/http/body/file'
7
+
8
+ Async.logger.debug! if ENV['ASYNC_LOGGER_DEBUG']
9
+
10
+ unless RUBY_PLATFORM =~ /java/
11
+ describe 'Async::HTTP::Client' do
12
+ include AsyncHttpClientSpecHelper
13
+
14
+ include_context "with WebMock",
15
+ :no_status_message,
16
+ :no_url_auth,
17
+ :no_content_length_header
18
+
19
+ it 'works' do
20
+ stub_request(:get, 'http://www.example.com')
21
+ expect(make_request(:get, 'http://www.example.com')).to eq(
22
+ status: 200,
23
+ headers: {},
24
+ body: nil
25
+ )
26
+ end
27
+
28
+ it 'works with request path' do
29
+ stub_request(:get, 'http://www.example.com/foo')
30
+ expect(make_request(:get, 'http://www.example.com/foo')).to eq(
31
+ status: 200,
32
+ headers: {},
33
+ body: nil
34
+ )
35
+ end
36
+
37
+ it 'works with request query' do
38
+ stub_request(:get, 'http://www.example.com/').with(
39
+ query: {
40
+ 'foo' => 'bar'
41
+ }
42
+ )
43
+ expect(make_request(:get, 'http://www.example.com/?foo=bar')).to eq(
44
+ status: 200,
45
+ headers: {},
46
+ body: nil
47
+ )
48
+ end
49
+
50
+ it 'works with request headers' do
51
+ stub_request(:get, 'http://www.example.com').with(
52
+ headers: {
53
+ 'X-Token' => 'Token'
54
+ }
55
+ )
56
+ expect(
57
+ make_request :get, 'http://www.example.com',
58
+ headers: {
59
+ 'X-Token' => 'Token'
60
+ }
61
+ ).to eq(
62
+ status: 200,
63
+ headers: {},
64
+ body: nil
65
+ )
66
+ end
67
+
68
+ it 'works with request body as text' do
69
+ stub_request(:post, 'http://www.example.com').with(
70
+ body: 'x'*10_000
71
+ )
72
+ expect(
73
+ make_request :post, 'http://www.example.com',
74
+ body: 'x'*10_000
75
+ ).to eq(
76
+ status: 200,
77
+ headers: {},
78
+ body: nil
79
+ )
80
+ end
81
+
82
+ it 'works with request body as file' do
83
+ stub_request(:post, "www.example.com").with(
84
+ body: File.read(__FILE__)
85
+ )
86
+ expect(
87
+ make_request :post, "http://www.example.com",
88
+ body: ::Protocol::HTTP::Body::File.open(__FILE__, block_size: 32)
89
+ ).to eq(
90
+ status: 200,
91
+ headers: {},
92
+ body: nil
93
+ )
94
+ end
95
+
96
+ it 'works with response status' do
97
+ stub_request(:get, 'http://www.example.com').to_return(
98
+ status: 400
99
+ )
100
+ expect(make_request(:get, 'http://www.example.com')).to eq(
101
+ status: 400,
102
+ headers: {},
103
+ body: nil
104
+ )
105
+ end
106
+
107
+ it 'works with response headers' do
108
+ stub_request(:get, 'http://www.example.com').to_return(
109
+ headers: {
110
+ 'X-Token' => 'TOKEN'
111
+ }
112
+ )
113
+ expect(make_request(:get, 'http://www.example.com')).to eq(
114
+ status: 200,
115
+ headers: {
116
+ 'x-token' => ['TOKEN']
117
+ },
118
+ body: nil
119
+ )
120
+ end
121
+
122
+ it 'works with response body' do
123
+ stub_request(:get, 'http://www.example.com').to_return(
124
+ body: 'abc'
125
+ )
126
+ expect(make_request(:get, 'http://www.example.com')).to eq(
127
+ status: 200,
128
+ headers: {},
129
+ body: 'abc'
130
+ )
131
+ end
132
+
133
+ it 'works with to_timeout' do
134
+ stub_request(:get, 'http://www.example.com').to_timeout
135
+ expect { make_request(:get, 'http://www.example.com') }.to raise_error Async::TimeoutError
136
+ end
137
+
138
+ it 'does not invoke "after real request" callbacks for stubbed requests' do
139
+ WebMock.allow_net_connect!
140
+ stub_request(:get, 'http://www.example.com').to_return(body: 'abc')
141
+
142
+ callback_invoked = false
143
+ WebMock.after_request(real_requests_only: true) { |_| callback_invoked = true }
144
+
145
+ make_request(:get, 'http://www.example.com')
146
+ expect(callback_invoked).to eq(false)
147
+ end
148
+
149
+ it 'does invoke "after request" callbacks for stubbed requests' do
150
+ WebMock.allow_net_connect!
151
+ stub_request(:get, 'http://www.example.com').to_return(body: 'abc')
152
+
153
+ callback_invoked = false
154
+ WebMock.after_request(real_requests_only: false) { |_| callback_invoked = true }
155
+
156
+ make_request(:get, 'http://www.example.com')
157
+ expect(callback_invoked).to eq(true)
158
+ end
159
+
160
+ context 'scheme and protocol' do
161
+ let(:default_response_headers) { {} }
162
+
163
+ before do
164
+ stub_request(
165
+ :get, "#{scheme}://www.example.com"
166
+ ).and_return(
167
+ body: 'BODY'
168
+ )
169
+ end
170
+
171
+ subject do
172
+ make_request(:get, "#{scheme}://www.example.com", protocol: protocol)
173
+ end
174
+
175
+ shared_examples :common do
176
+ specify do
177
+ expect(subject).to eq(
178
+ status: 200,
179
+ headers: default_response_headers,
180
+ body: 'BODY'
181
+ )
182
+ end
183
+ end
184
+
185
+ context 'http scheme' do
186
+ let(:scheme) { 'http' }
187
+
188
+ context 'default protocol' do
189
+ let(:protocol) { nil }
190
+
191
+ include_examples :common
192
+ end
193
+
194
+ context 'HTTP10 protocol' do
195
+ let(:protocol) { Async::HTTP::Protocol::HTTP10 }
196
+ let(:default_response_headers) { {"connection"=>["keep-alive"]} }
197
+
198
+ include_examples :common
199
+ end
200
+
201
+ context 'HTTP11 protocol' do
202
+ let(:protocol) { Async::HTTP::Protocol::HTTP11 }
203
+
204
+ include_examples :common
205
+ end
206
+
207
+ context 'HTTP2 protocol' do
208
+ let(:protocol) { Async::HTTP::Protocol::HTTP2 }
209
+
210
+ include_examples :common
211
+ end
212
+ end
213
+
214
+ context 'https scheme' do
215
+ let(:scheme) { 'https' }
216
+
217
+ context 'default protocol' do
218
+ let(:protocol) { nil }
219
+
220
+ include_examples :common
221
+ end
222
+
223
+ context 'HTTP10 protocol' do
224
+ let(:protocol) { Async::HTTP::Protocol::HTTP10 }
225
+ let(:default_response_headers) { {"connection"=>["keep-alive"]} }
226
+
227
+ include_examples :common
228
+ end
229
+
230
+ context 'HTTP11 protocol' do
231
+ let(:protocol) { Async::HTTP::Protocol::HTTP11 }
232
+
233
+ include_examples :common
234
+ end
235
+
236
+ context 'HTTP2 protocol' do
237
+ let(:protocol) { Async::HTTP::Protocol::HTTP2 }
238
+
239
+ include_examples :common
240
+ end
241
+
242
+ context 'HTTPS protocol' do
243
+ let(:protocol) { Async::HTTP::Protocol::HTTPS }
244
+
245
+ include_examples :common
246
+ end
247
+ end
248
+ end
249
+
250
+ context 'multiple requests' do
251
+ let(:endpoint) { Async::HTTP::Endpoint.parse('http://www.example.com') }
252
+ let(:requests_count) { 3 }
253
+
254
+ shared_examples :common do
255
+ before do
256
+ requests_count.times do |index|
257
+ stub_request(
258
+ :get, "http://www.example.com/foo#{index}"
259
+ ).to_return(
260
+ status: 200 + index,
261
+ headers: {'X-Token' => "foo#{index}"},
262
+ body: "FOO#{index}"
263
+ )
264
+ end
265
+ end
266
+
267
+ specify do
268
+ expect(subject).to eq(
269
+ 0 => {
270
+ status: 200,
271
+ headers: {'x-token' => ['foo0']},
272
+ body: 'FOO0'
273
+ },
274
+ 1 => {
275
+ status: 201,
276
+ headers: {'x-token' => ['foo1']},
277
+ body: 'FOO1'
278
+ },
279
+ 2 => {
280
+ status: 202,
281
+ headers: {'x-token' => ['foo2']},
282
+ body: 'FOO2'
283
+ }
284
+ )
285
+ end
286
+ end
287
+
288
+ context 'sequential' do
289
+ subject do
290
+ responses = {}
291
+ Async do |task|
292
+ Async::HTTP::Client.open(endpoint, protocol) do |client|
293
+ requests_count.times do |index|
294
+ response = client.get "/foo#{index}"
295
+ responses[index] = response_to_hash(response)
296
+ end
297
+ end
298
+ end
299
+ responses
300
+ end
301
+
302
+ context 'HTTP1 protocol' do
303
+ let(:protocol) { Async::HTTP::Protocol::HTTP1 }
304
+
305
+ include_examples :common
306
+ end
307
+
308
+ context 'HTTP2 protocol' do
309
+ let(:protocol) { Async::HTTP::Protocol::HTTP2 }
310
+
311
+ include_examples :common
312
+ end
313
+ end
314
+
315
+ context 'asynchronous' do
316
+ subject do
317
+ responses = {}
318
+ Async do |task|
319
+ Async::HTTP::Client.open(endpoint, protocol) do |client|
320
+ tasks = requests_count.times.map do |index|
321
+ task.async do
322
+ response = client.get "/foo#{index}"
323
+ responses[index] = response_to_hash(response)
324
+ end
325
+ end
326
+
327
+ tasks.map(&:wait)
328
+ end
329
+ end
330
+ responses
331
+ end
332
+
333
+ context 'HTTP1 protocol' do
334
+ let(:protocol) { Async::HTTP::Protocol::HTTP1 }
335
+
336
+ include_examples :common
337
+ end
338
+
339
+ context 'HTTP2 protocol' do
340
+ let(:protocol) { Async::HTTP::Protocol::HTTP2 }
341
+
342
+ include_examples :common
343
+ end
344
+ end
345
+ end
346
+
347
+ def make_request(method, url, protocol: nil, headers: {}, body: nil)
348
+ Async do
349
+ endpoint = Async::HTTP::Endpoint.parse(url)
350
+
351
+ begin
352
+ Async::HTTP::Client.open(endpoint, protocol || endpoint.protocol) do |client|
353
+ response = client.send(
354
+ method,
355
+ endpoint.path,
356
+ headers,
357
+ body
358
+ )
359
+ response_to_hash(response)
360
+ end
361
+ rescue Async::TimeoutError => e
362
+ e
363
+ end
364
+ end.wait
365
+ end
366
+
367
+ def response_to_hash(response)
368
+ {
369
+ status: response.status,
370
+ headers: response.headers.to_h,
371
+ body: response.read
372
+ }
373
+ end
374
+ end
375
+ end
@@ -0,0 +1,73 @@
1
+ module AsyncHttpClientSpecHelper
2
+ def http_request(method, url, options = {}, &block)
3
+ endpoint = Async::HTTP::Endpoint.parse(url)
4
+
5
+ path = endpoint.path
6
+ path = path + "?" + options[:query] if options[:query]
7
+
8
+ headers = (options[:headers] || {}).each_with_object([]) do |(k, v), o|
9
+ Array(v).each do |v|
10
+ o.push [k, v]
11
+ end
12
+ end
13
+ headers.push(
14
+ ['authorization', 'Basic ' + Base64.strict_encode64(options[:basic_auth].join(':'))]
15
+ ) if options[:basic_auth]
16
+
17
+ body = options[:body]
18
+
19
+ Async do
20
+ begin
21
+ Async::HTTP::Client.open(endpoint) do |client|
22
+ response = client.send(
23
+ method,
24
+ path,
25
+ headers,
26
+ body
27
+ )
28
+
29
+ OpenStruct.new(
30
+ build_hash_response(response)
31
+ )
32
+ end
33
+ rescue Exception => e
34
+ e
35
+ end
36
+ end.wait
37
+ end
38
+
39
+ def client_timeout_exception_class
40
+ Async::TimeoutError
41
+ end
42
+
43
+ def connection_refused_exception_class
44
+ Errno::ECONNREFUSED
45
+ end
46
+
47
+ def http_library
48
+ :async_http_client
49
+ end
50
+
51
+ private
52
+
53
+ def build_hash_response(response)
54
+ {
55
+
56
+ status: response.status.to_s,
57
+ message: Protocol::HTTP1::Reason::DESCRIPTIONS[response.status],
58
+ headers: build_response_headers(response),
59
+ body: response.read
60
+ }
61
+ end
62
+
63
+ def build_response_headers(response)
64
+ response.headers.each.each_with_object({}) do |(k, v), o|
65
+ o[k] ||= []
66
+ o[k] << v
67
+ end.tap do |o|
68
+ o.each do |k, v|
69
+ o[k] = v.join(', ')
70
+ end
71
+ end
72
+ end
73
+ end
@@ -474,18 +474,25 @@ unless RUBY_PLATFORM =~ /java/
474
474
  include CurbSpecHelper::ClassPerform
475
475
  end
476
476
 
477
- describe "using .reset" do
477
+ describe "using #reset" do
478
478
  before do
479
479
  @curl = Curl::Easy.new
480
480
  @curl.url = "http://example.com"
481
- body = "on_success fired"
482
- stub_request(:any, "example.com").to_return(body: body)
481
+ stub_request(:any, "example.com").
482
+ to_return(body: "abc",
483
+ headers: { "Content-Type" => "application/json" })
483
484
  @curl.http_get
484
485
  end
485
486
 
486
- it "should clear the body_str" do
487
+ it "should clear all memoized response fields" do
487
488
  @curl.reset
488
- expect(@curl.body_str).to eq(nil)
489
+ expect(@curl).to have_attributes(
490
+ body_str: nil,
491
+ content_type: nil,
492
+ header_str: nil,
493
+ last_effective_url: nil,
494
+ response_code: 0,
495
+ )
489
496
  end
490
497
  end
491
498
  end
@@ -71,6 +71,35 @@ unless RUBY_PLATFORM =~ /java/
71
71
  end
72
72
  end
73
73
 
74
+ it "only calls request middleware once" do
75
+ stub_request(:get, "www.example.com")
76
+
77
+ middleware = Class.new do
78
+ def self.called!
79
+ @called = called + 1
80
+ end
81
+
82
+ def self.called
83
+ @called || 0
84
+ end
85
+
86
+ def request(client, head, body)
87
+ self.class.called!
88
+ [head, body]
89
+ end
90
+ end
91
+
92
+ EM.run do
93
+ conn = EventMachine::HttpRequest.new('http://www.example.com/')
94
+ conn.use middleware
95
+ http = conn.get
96
+ http.callback do
97
+ expect(middleware.called).to eq(1)
98
+ EM.stop
99
+ end
100
+ end
101
+ end
102
+
74
103
  let(:response_middleware) do
75
104
  Class.new do
76
105
  def response(resp)
@@ -119,6 +148,33 @@ unless RUBY_PLATFORM =~ /java/
119
148
  context 'making a real request', net_connect: true do
120
149
  before { WebMock.allow_net_connect! }
121
150
  include_examples "em-http-request middleware/after_request hook integration"
151
+
152
+ it "only calls request middleware once" do
153
+ middleware = Class.new do
154
+ def self.called!
155
+ @called = called + 1
156
+ end
157
+
158
+ def self.called
159
+ @called || 0
160
+ end
161
+
162
+ def request(client, head, body)
163
+ self.class.called!
164
+ [head, body]
165
+ end
166
+ end
167
+
168
+ EM.run do
169
+ conn = EventMachine::HttpRequest.new(webmock_server_url)
170
+ conn.use middleware
171
+ http = conn.get
172
+ http.callback do
173
+ expect(middleware.called).to eq(1)
174
+ EM.stop
175
+ end
176
+ end
177
+ end
122
178
  end
123
179
 
124
180
  context 'when the request is stubbed' do
@@ -50,7 +50,7 @@ module EMHttpRequestSpecHelper
50
50
  end
51
51
 
52
52
  def client_timeout_exception_class
53
- "WebMock timeout error"
53
+ 'Errno::ETIMEDOUT'
54
54
  end
55
55
 
56
56
  def connection_refused_exception_class
@@ -28,6 +28,8 @@ module ExconSpecHelper
28
28
  res
29
29
  end
30
30
 
31
+ Excon.set_raise_on_warnings!(true)
32
+
31
33
  OpenStruct.new \
32
34
  body: response.body,
33
35
  headers: headers,
@@ -72,6 +72,17 @@ describe "HTTP.rb" do
72
72
  end
73
73
 
74
74
  context "streamer" do
75
+ it "can be read to a provided buffer" do
76
+ stub_request(:get, "example.com/foo")
77
+ .to_return(status: 200, body: "Hello world! ")
78
+ response = HTTP.get "http://example.com/foo"
79
+
80
+ buffer = ""
81
+ response.body.readpartial(1024, buffer)
82
+
83
+ expect(buffer).to eq "Hello world! "
84
+ end
85
+
75
86
  it "can be closed" do
76
87
  stub_request :get, "example.com/foo"
77
88
  response = HTTP.get "http://example.com/foo"
@@ -51,6 +51,57 @@ if RUBY_PLATFORM =~ /java/
51
51
  response = Manticore.head("http://example-foo.com")
52
52
  expect(response.code).to eq(204)
53
53
  end
54
+
55
+ context "when a custom failure handler is defined" do
56
+ let(:failure_handler) { proc {} }
57
+
58
+ before do
59
+ allow(failure_handler).to receive(:call).with(kind_of(Manticore::Timeout)) do |ex|
60
+ raise ex
61
+ end
62
+ end
63
+
64
+ it "handles timeouts by invoking the failure handler" do
65
+ stub_request(:get, "http://example-foo.com").to_timeout
66
+ request = Manticore.get("http://example-foo.com").tap do |req|
67
+ req.on_failure(&failure_handler)
68
+ end
69
+ expect { request.call }.to raise_error(Manticore::Timeout)
70
+ expect(failure_handler).to have_received(:call)
71
+ end
72
+ end
73
+
74
+ context 'when used in a streaming mode' do
75
+ let(:webmock_server_url) {"http://#{WebMockServer.instance.host_with_port}/"}
76
+ let(:result_chunks) { [] }
77
+
78
+ def manticore_streaming_get
79
+ Manticore.get(webmock_server_url).tap do |req|
80
+ req.on_success do |response|
81
+ response.body do |chunk|
82
+ result_chunks << chunk
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ context 'when connections are allowed' do
89
+ it 'works' do
90
+ WebMock.allow_net_connect!
91
+ expect { manticore_streaming_get.call }.to_not raise_error
92
+ expect(result_chunks).to_not be_empty
93
+ end
94
+ end
95
+
96
+ context 'when stubbed' do
97
+ it 'works' do
98
+ stub_body = 'hello!'
99
+ stub_request(:get, webmock_server_url).to_return(body: stub_body)
100
+ expect { manticore_streaming_get.call }.to_not raise_error
101
+ expect(result_chunks).to eq [stub_body]
102
+ end
103
+ end
104
+ end
54
105
  end
55
106
  end
56
107
  end
@@ -201,6 +201,18 @@ describe "Net:HTTP" do
201
201
  expect(Net::HTTP.get_response(Addressable::URI.parse('http://www.example.com/hello?a=1')).body).to eq("abc")
202
202
  end
203
203
 
204
+ it "should support method calls on stubbed socket" do
205
+ WebMock.allow_net_connect!
206
+ stub_request(:get, 'www.google.com')#.with(headers: {"My-Header" => 99})
207
+ req = Net::HTTP::Get.new('/')
208
+ Net::HTTP.start('www.google.com') do |http|
209
+ http.request(req, '')
210
+ socket = http.instance_variable_get(:@socket)
211
+ expect(socket).to be_a(StubSocket)
212
+ expect { socket.io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) }.to_not raise_error
213
+ end
214
+ end
215
+
204
216
  describe "connecting on Net::HTTP.start" do
205
217
  before(:each) do
206
218
  @http = Net::HTTP.new('www.google.com', 443)
@@ -328,4 +340,30 @@ describe "Net:HTTP" do
328
340
  http.request(req, '')
329
341
  end
330
342
  end
343
+
344
+ describe "hostname handling" do
345
+ it "should set brackets around the hostname if it is an IPv6 address" do
346
+ net_http = Net::HTTP.new('b2dc:5bdf:4f0d::3014:e0ca', 80)
347
+ path = '/example.jpg'
348
+ expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://[b2dc:5bdf:4f0d::3014:e0ca]:80/example.jpg')
349
+ end
350
+
351
+ it "should not set brackets around the hostname if it is already wrapped by brackets" do
352
+ net_http = Net::HTTP.new('[b2dc:5bdf:4f0d::3014:e0ca]', 80)
353
+ path = '/example.jpg'
354
+ expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://[b2dc:5bdf:4f0d::3014:e0ca]:80/example.jpg')
355
+ end
356
+
357
+ it "should not set brackets around the hostname if it is an IPv4 address" do
358
+ net_http = Net::HTTP.new('181.152.137.168', 80)
359
+ path = '/example.jpg'
360
+ expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://181.152.137.168:80/example.jpg')
361
+ end
362
+
363
+ it "should not set brackets around the hostname if it is a domain" do
364
+ net_http = Net::HTTP.new('www.example.com', 80)
365
+ path = '/example.jpg'
366
+ expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://www.example.com:80/example.jpg')
367
+ end
368
+ end
331
369
  end
@@ -28,8 +28,8 @@ module PatronSpecHelper
28
28
  end
29
29
  end
30
30
 
31
- status_line_pattern = %r(\AHTTP/(\d+\.\d+)\s+(\d\d\d)\s*([^\r\n]+)?)
32
- message = response.status_line.match(status_line_pattern)[3] || ""
31
+ status_line_pattern = %r(\AHTTP/(\d+(\.\d+)?)\s+(\d\d\d)\s*([^\r\n]+)?)
32
+ message = response.status_line.match(status_line_pattern)[4] || ""
33
33
 
34
34
  OpenStruct.new({
35
35
  body: response.body,