webmock 3.9.1 → 3.18.1

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/CI.yml +38 -0
  3. data/CHANGELOG.md +180 -6
  4. data/Gemfile +1 -1
  5. data/README.md +63 -30
  6. data/Rakefile +12 -2
  7. data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +11 -4
  8. data/lib/webmock/http_lib_adapters/curb_adapter.rb +2 -2
  9. data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +6 -3
  10. data/lib/webmock/http_lib_adapters/http_rb/client.rb +2 -1
  11. data/lib/webmock/http_lib_adapters/http_rb/response.rb +17 -3
  12. data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +4 -2
  13. data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +6 -2
  14. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +23 -6
  15. data/lib/webmock/http_lib_adapters/manticore_adapter.rb +8 -1
  16. data/lib/webmock/http_lib_adapters/net_http.rb +29 -115
  17. data/lib/webmock/request_pattern.rb +30 -8
  18. data/lib/webmock/request_signature.rb +2 -2
  19. data/lib/webmock/request_stub.rb +15 -0
  20. data/lib/webmock/response.rb +19 -13
  21. data/lib/webmock/stub_registry.rb +24 -9
  22. data/lib/webmock/test_unit.rb +1 -3
  23. data/lib/webmock/version.rb +1 -1
  24. data/lib/webmock/webmock.rb +12 -2
  25. data/minitest/webmock_spec.rb +1 -1
  26. data/spec/acceptance/async_http_client/async_http_client_spec.rb +27 -5
  27. data/spec/acceptance/curb/curb_spec.rb +11 -0
  28. data/spec/acceptance/em_http_request/em_http_request_spec.rb +57 -1
  29. data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +1 -1
  30. data/spec/acceptance/excon/excon_spec.rb +2 -2
  31. data/spec/acceptance/manticore/manticore_spec.rb +32 -0
  32. data/spec/acceptance/net_http/net_http_shared.rb +46 -9
  33. data/spec/acceptance/net_http/net_http_spec.rb +75 -23
  34. data/spec/acceptance/net_http/real_net_http_spec.rb +1 -1
  35. data/spec/acceptance/patron/patron_spec.rb +19 -21
  36. data/spec/acceptance/patron/patron_spec_helper.rb +2 -2
  37. data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +14 -14
  38. data/spec/acceptance/shared/callbacks.rb +2 -2
  39. data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +1 -1
  40. data/spec/acceptance/shared/stubbing_requests.rb +17 -0
  41. data/spec/unit/request_pattern_spec.rb +82 -46
  42. data/spec/unit/request_signature_spec.rb +21 -1
  43. data/spec/unit/request_stub_spec.rb +35 -0
  44. data/spec/unit/response_spec.rb +51 -19
  45. data/spec/unit/webmock_spec.rb +54 -0
  46. data/test/test_webmock.rb +6 -0
  47. data/webmock.gemspec +6 -5
  48. metadata +49 -35
  49. data/.travis.yml +0 -24
@@ -135,6 +135,28 @@ unless RUBY_PLATFORM =~ /java/
135
135
  expect { make_request(:get, 'http://www.example.com') }.to raise_error Async::TimeoutError
136
136
  end
137
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
+
138
160
  context 'scheme and protocol' do
139
161
  let(:default_response_headers) { {} }
140
162
 
@@ -226,7 +248,7 @@ unless RUBY_PLATFORM =~ /java/
226
248
  end
227
249
 
228
250
  context 'multiple requests' do
229
- let(:endpoint) { Async::HTTP::Endpoint.parse('http://www.example.com') }
251
+ let!(:endpoint) { Async::HTTP::Endpoint.parse('http://www.example.com') }
230
252
  let(:requests_count) { 3 }
231
253
 
232
254
  shared_examples :common do
@@ -278,13 +300,13 @@ unless RUBY_PLATFORM =~ /java/
278
300
  end
279
301
 
280
302
  context 'HTTP1 protocol' do
281
- let(:protocol) { Async::HTTP::Protocol::HTTP1 }
303
+ let!(:protocol) { Async::HTTP::Protocol::HTTP1 }
282
304
 
283
305
  include_examples :common
284
306
  end
285
307
 
286
308
  context 'HTTP2 protocol' do
287
- let(:protocol) { Async::HTTP::Protocol::HTTP2 }
309
+ let!(:protocol) { Async::HTTP::Protocol::HTTP2 }
288
310
 
289
311
  include_examples :common
290
312
  end
@@ -309,13 +331,13 @@ unless RUBY_PLATFORM =~ /java/
309
331
  end
310
332
 
311
333
  context 'HTTP1 protocol' do
312
- let(:protocol) { Async::HTTP::Protocol::HTTP1 }
334
+ let!(:protocol) { Async::HTTP::Protocol::HTTP1 }
313
335
 
314
336
  include_examples :common
315
337
  end
316
338
 
317
339
  context 'HTTP2 protocol' do
318
- let(:protocol) { Async::HTTP::Protocol::HTTP2 }
340
+ let!(:protocol) { Async::HTTP::Protocol::HTTP2 }
319
341
 
320
342
  include_examples :common
321
343
  end
@@ -383,6 +383,17 @@ unless RUBY_PLATFORM =~ /java/
383
383
  expect(c.body).to eq("abc")
384
384
  end
385
385
 
386
+ it "supports headers containing the ':' character" do
387
+ stub_request(:get, "www.example.com").with(headers: {'Referer'=>'http://www.example.com'}).to_return(body: "abc")
388
+
389
+ c = Curl::Easy.new
390
+ c.url = "http://www.example.com"
391
+ c.headers = ["Referer: http://www.example.com"]
392
+ c.http(:GET)
393
+ expect(c.body).to eq("abc")
394
+ expect(c.headers).to eq(["Referer: http://www.example.com"])
395
+ end
396
+
386
397
  describe 'match request body' do
387
398
  it 'for post' do
388
399
  stub_request(:post, "www.example.com").with(body: 'foo=nhe').to_return(body: "abc")
@@ -22,7 +22,7 @@ unless RUBY_PLATFORM =~ /java/
22
22
 
23
23
  def make_request
24
24
  EM.run do
25
- request = EM::HttpRequest.new(http_url).get(redirects: 1)
25
+ request = EM::HttpRequest.new(http_url, ssl: {verify_peer: true}).get(redirects: 1)
26
26
  request.callback { EM.stop }
27
27
  end
28
28
  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
@@ -16,7 +16,7 @@ module EMHttpRequestSpecHelper
16
16
  error_set = false
17
17
  uri = Addressable::URI.heuristic_parse(uri)
18
18
  EventMachine.run {
19
- request = EventMachine::HttpRequest.new("#{uri.normalize.to_s}")
19
+ request = EventMachine::HttpRequest.new("#{uri.normalize.to_s}", ssl: {verify_peer: true})
20
20
  http = request.send(method, {
21
21
  timeout: 30,
22
22
  body: options[:body],
@@ -20,7 +20,7 @@ describe "Excon" do
20
20
  it "should support excon response_block for real requests", net_connect: true do
21
21
  a = []
22
22
  WebMock.allow_net_connect!
23
- r = Excon.new('http://httpstat.us/200', headers: { "Accept" => "*" }).
23
+ r = Excon.new('https://httpstat.us/200', headers: { "Accept" => "*" }).
24
24
  get(response_block: lambda {|e, remaining, total| a << e}, chunk_size: 1)
25
25
  expect(a).to eq(["2", "0", "0", " ", "O", "K"])
26
26
  expect(r.body).to eq("")
@@ -41,7 +41,7 @@ describe "Excon" do
41
41
  WebMock.after_request { |_, res|
42
42
  response = res
43
43
  }
44
- r = Excon.new('http://httpstat.us/200', headers: { "Accept" => "*" }).
44
+ r = Excon.new('https://httpstat.us/200', headers: { "Accept" => "*" }).
45
45
  get(response_block: lambda {|e, remaining, total| a << e}, chunk_size: 1)
46
46
  expect(response.body).to eq("200 OK")
47
47
  expect(a).to eq(["2", "0", "0", " ", "O", "K"])
@@ -70,6 +70,38 @@ if RUBY_PLATFORM =~ /java/
70
70
  expect(failure_handler).to have_received(:call)
71
71
  end
72
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
73
105
  end
74
106
  end
75
107
  end
@@ -1,3 +1,5 @@
1
+ require 'set'
2
+
1
3
  shared_examples_for "Net::HTTP" do
2
4
  describe "when making real requests", net_connect: true do
3
5
  let(:port){ WebMockServer.instance.port }
@@ -26,21 +28,56 @@ shared_examples_for "Net::HTTP" do
26
28
 
27
29
  it "should connect only once when connected on start", net_connect: true do
28
30
  @http = Net::HTTP.new('localhost', port)
29
- socket_id_before_request = socket_id_after_request = nil
31
+ socket_before_request = socket_after_request = nil
30
32
  @http.start {|conn|
31
- socket_id_before_request = conn.instance_variable_get(:@socket).object_id
33
+ socket_before_request = conn.instance_variable_get(:@socket)
32
34
  conn.request(Net::HTTP::Get.new("/"))
33
- socket_id_after_request = conn.instance_variable_get(:@socket).object_id
35
+ socket_after_request = conn.instance_variable_get(:@socket)
34
36
  }
35
37
 
36
- if !defined?(WebMock::Config) || WebMock::Config.instance.net_http_connect_on_start
37
- expect(socket_id_before_request).not_to eq(nil.object_id)
38
- expect(socket_id_after_request).not_to eq(nil.object_id)
39
- expect(socket_id_after_request).to eq(socket_id_before_request)
38
+ if !defined?(WebMock::NetHTTPUtility) || WebMock::Config.instance.net_http_connect_on_start
39
+ expect(socket_before_request).to be_a(Net::BufferedIO)
40
+ expect(socket_after_request).to be_a(Net::BufferedIO)
41
+ expect(socket_after_request).to be(socket_before_request)
42
+ else
43
+ expect(socket_before_request).to be_a(StubSocket)
44
+ expect(socket_after_request).to be_a(Net::BufferedIO)
45
+ end
46
+ end
47
+
48
+ it "should allow sending multiple requests when persisted", net_connect: true do
49
+ @http = Net::HTTP.new('example.org')
50
+ @http.start
51
+ expect(@http.get("/")).to be_a(Net::HTTPSuccess)
52
+ expect(@http.get("/")).to be_a(Net::HTTPSuccess)
53
+ expect(@http.get("/")).to be_a(Net::HTTPSuccess)
54
+ @http.finish
55
+ end
56
+
57
+ it "should not leak file descriptors", net_connect: true do
58
+ sockets = Set.new
59
+
60
+ @http = Net::HTTP.new('example.org')
61
+ @http.start
62
+ sockets << @http.instance_variable_get(:@socket)
63
+ @http.get("/")
64
+ sockets << @http.instance_variable_get(:@socket)
65
+ @http.get("/")
66
+ sockets << @http.instance_variable_get(:@socket)
67
+ @http.get("/")
68
+ sockets << @http.instance_variable_get(:@socket)
69
+ @http.finish
70
+
71
+ if !defined?(WebMock::NetHTTPUtility) || WebMock.net_http_connect_on_start?(Addressable::URI.parse("http://example.com/"))
72
+ expect(sockets.length).to eq(1)
73
+ expect(sockets.to_a[0]).to be_a(Net::BufferedIO)
40
74
  else
41
- expect(socket_id_before_request).to eq(nil.object_id)
42
- expect(socket_id_after_request).not_to eq(nil.object_id)
75
+ expect(sockets.length).to eq(2)
76
+ expect(sockets.to_a[0]).to be_a(StubSocket)
77
+ expect(sockets.to_a[1]).to be_a(Net::BufferedIO)
43
78
  end
79
+
80
+ expect(sockets.all?(&:closed?)).to be(true)
44
81
  end
45
82
 
46
83
  it "should pass the read_timeout value on", net_connect: true do
@@ -115,33 +115,16 @@ describe "Net:HTTP" do
115
115
  expect(Net::HTTP.start("www.example.com") { |http| http.request(req)}.body).to eq("abc")
116
116
  end
117
117
 
118
- it "raises an ArgumentError if passed headers as symbols if RUBY_VERSION < 2.3.0" do
118
+ it "raises an ArgumentError if passed headers as symbols" do
119
119
  uri = URI.parse("http://google.com/")
120
120
  http = Net::HTTP.new(uri.host, uri.port)
121
121
  request = Net::HTTP::Get.new(uri.request_uri)
122
+ request[:InvalidHeaderSinceItsASymbol] = "this will not be valid"
122
123
 
123
- # Net::HTTP calls downcase on header keys assigned with []=
124
- # In Ruby 1.8.7 symbols do not respond to downcase
125
- #
126
- # Meaning you can not assign header keys as symbols in ruby 1.8.7 using []=
127
- if :symbol.respond_to?(:downcase)
128
- request[:InvalidHeaderSinceItsASymbol] = "this will not be valid"
129
- else
130
- request.instance_eval do
131
- @header = request.to_hash.merge({InvalidHeaderSinceItsASymbol: "this will not be valid"})
132
- end
133
- end
134
-
135
- if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.3.0')
136
- expect do
137
- http.request(request)
138
- end.to raise_error ArgumentError, "Net:HTTP does not accept headers as symbols"
139
- else
140
- stub_http_request(:get, "google.com").with(headers: { InvalidHeaderSinceItsASymbol: "this will not be valid" })
141
- expect do
142
- http.request(request)
143
- end.not_to raise_error
144
- end
124
+ stub_http_request(:get, "google.com").with(headers: { InvalidHeaderSinceItsASymbol: "this will not be valid" })
125
+ expect do
126
+ http.request(request)
127
+ end.not_to raise_error
145
128
  end
146
129
 
147
130
  it "should handle multiple values for the same response header" do
@@ -213,6 +196,22 @@ describe "Net:HTTP" do
213
196
  end
214
197
  end
215
198
 
199
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0')
200
+ it "uses the StubSocket to provide IP address" do
201
+ Net::HTTP.start("http://example.com") do |http|
202
+ expect(http.ipaddr).to eq("127.0.0.1")
203
+ end
204
+ end
205
+ end
206
+
207
+ it "defines common socket methods" do
208
+ Net::HTTP.start("http://example.com") do |http|
209
+ socket = http.instance_variable_get(:@socket)
210
+ expect(socket.io.ssl_version).to eq("TLSv1.3")
211
+ expect(socket.io.cipher).to eq(["TLS_AES_128_GCM_SHA256", "TLSv1.3", 128, 128])
212
+ end
213
+ end
214
+
216
215
  describe "connecting on Net::HTTP.start" do
217
216
  before(:each) do
218
217
  @http = Net::HTTP.new('www.google.com', 443)
@@ -254,6 +253,21 @@ describe "Net:HTTP" do
254
253
  }
255
254
  end
256
255
 
256
+ it "should connect to the server on start when allowlisted", net_connect: true do
257
+ WebMock.disable_net_connect!(allow: "www.google.com", net_http_connect_on_start: "www.google.com")
258
+ @http.start {|conn|
259
+ cert = OpenSSL::X509::Certificate.new conn.peer_cert
260
+ expect(cert).to be_a(OpenSSL::X509::Certificate)
261
+ }
262
+ end
263
+
264
+ it "should not connect to the server on start when not allowlisted", net_connect: true do
265
+ WebMock.disable_net_connect!(allow: "www.google.com", net_http_connect_on_start: "www.yahoo.com")
266
+ @http.start {|conn|
267
+ expect(conn.peer_cert).to be_nil
268
+ }
269
+ end
270
+
257
271
  it "should connect to the server if the URI matches an regex", net_connect: true do
258
272
  WebMock.disable_net_connect!(allow: /google.com/)
259
273
  Net::HTTP.get('www.google.com','/')
@@ -282,6 +296,13 @@ describe "Net:HTTP" do
282
296
  it_should_behave_like "Net::HTTP"
283
297
  end
284
298
 
299
+ describe "when net_http_connect_on_start is a specific host" do
300
+ before(:each) do
301
+ WebMock.allow_net_connect!(net_http_connect_on_start: "localhost")
302
+ end
303
+ it_should_behave_like "Net::HTTP"
304
+ end
305
+
285
306
  describe 'after_request callback support', net_connect: true do
286
307
  let(:expected_body_regex) { /hello world/ }
287
308
 
@@ -340,4 +361,35 @@ describe "Net:HTTP" do
340
361
  http.request(req, '')
341
362
  end
342
363
  end
364
+
365
+ describe "hostname handling" do
366
+ it "should set brackets around the hostname if it is an IPv6 address" do
367
+ net_http = Net::HTTP.new('b2dc:5bdf:4f0d::3014:e0ca', 80)
368
+ path = '/example.jpg'
369
+ expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://[b2dc:5bdf:4f0d::3014:e0ca]:80/example.jpg')
370
+ end
371
+
372
+ it "should not set brackets around the hostname if it is already wrapped by brackets" do
373
+ net_http = Net::HTTP.new('[b2dc:5bdf:4f0d::3014:e0ca]', 80)
374
+ path = '/example.jpg'
375
+ expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://[b2dc:5bdf:4f0d::3014:e0ca]:80/example.jpg')
376
+ end
377
+
378
+ it "should not set brackets around the hostname if it is an IPv4 address" do
379
+ net_http = Net::HTTP.new('181.152.137.168', 80)
380
+ path = '/example.jpg'
381
+ expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://181.152.137.168:80/example.jpg')
382
+ end
383
+
384
+ it "should not set brackets around the hostname if it is a domain" do
385
+ net_http = Net::HTTP.new('www.example.com', 80)
386
+ path = '/example.jpg'
387
+ expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://www.example.com:80/example.jpg')
388
+ end
389
+
390
+ it "does not require a path" do
391
+ net_http = Net::HTTP.new('www.example.com', 80)
392
+ expect(WebMock::NetHTTPUtility.get_uri(net_http)).to eq('http://www.example.com:80')
393
+ end
394
+ end
343
395
  end
@@ -17,4 +17,4 @@ describe "Real Net:HTTP without webmock", without_webmock: true do
17
17
  end
18
18
 
19
19
  it_should_behave_like "Net::HTTP"
20
- end
20
+ end
@@ -93,31 +93,29 @@ unless RUBY_PLATFORM =~ /java/
93
93
  @sess.copy("/abc", "/def")
94
94
  end
95
95
 
96
- if /^1\.9/ === RUBY_VERSION
97
- describe "handling encoding same way as patron" do
98
- around(:each) do |example|
99
- @encoding = Encoding.default_internal
100
- Encoding.default_internal = "UTF-8"
101
- example.run
102
- Encoding.default_internal = @encoding
103
- end
96
+ describe "handling encoding same way as patron" do
97
+ around(:each) do |example|
98
+ @encoding = Encoding.default_internal
99
+ Encoding.default_internal = "UTF-8"
100
+ example.run
101
+ Encoding.default_internal = @encoding
102
+ end
104
103
 
105
- it "should not encode body with default encoding" do
106
- stub_request(:get, "www.example.com").
107
- to_return(body: "Øl")
104
+ it "should not encode body with default encoding" do
105
+ stub_request(:get, "www.example.com").
106
+ to_return(body: "Øl")
108
107
 
109
- expect(@sess.get("").body.encoding).to eq(Encoding::ASCII_8BIT)
110
- expect(@sess.get("").inspectable_body.encoding).to eq(Encoding::UTF_8)
111
- end
108
+ expect(@sess.get("").body.encoding).to eq(Encoding::ASCII_8BIT)
109
+ expect(@sess.get("").inspectable_body.encoding).to eq(Encoding::UTF_8)
110
+ end
112
111
 
113
- it "should not encode body to default internal" do
114
- stub_request(:get, "www.example.com").
115
- to_return(headers: {'Content-Type' => 'text/html; charset=iso-8859-1'},
116
- body: "Øl".encode("iso-8859-1"))
112
+ it "should not encode body to default internal" do
113
+ stub_request(:get, "www.example.com").
114
+ to_return(headers: {'Content-Type' => 'text/html; charset=iso-8859-1'},
115
+ body: "Øl".encode("iso-8859-1"))
117
116
 
118
- expect(@sess.get("").body.encoding).to eq(Encoding::ASCII_8BIT)
119
- expect(@sess.get("").decoded_body.encoding).to eq(Encoding.default_internal)
120
- end
117
+ expect(@sess.get("").body.encoding).to eq(Encoding::ASCII_8BIT)
118
+ expect(@sess.get("").decoded_body.encoding).to eq(Encoding.default_internal)
121
119
  end
122
120
  end
123
121
  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,
@@ -91,7 +91,7 @@ shared_context "allowing and disabling net connect" do |*adapter_info|
91
91
  describe "is not allowed, with exceptions" do
92
92
  describe "allowing by host string" do
93
93
  before :each do
94
- WebMock.disable_net_connect!(allow: 'httpstat.us')
94
+ WebMock.disable_net_connect!(allow: 'https://httpstat.us')
95
95
  end
96
96
 
97
97
  context "when the host is not allowed" do
@@ -109,13 +109,13 @@ shared_context "allowing and disabling net connect" do |*adapter_info|
109
109
 
110
110
  context "when the host is allowed" do
111
111
  it "should return stubbed response if request was stubbed" do
112
- stub_request(:get, 'httpstat.us/200').to_return(body: "abc")
113
- expect(http_request(:get, "http://httpstat.us/200").body).to eq("abc")
112
+ stub_request(:get, 'https://httpstat.us/200').to_return(body: "abc")
113
+ expect(http_request(:get, "https://httpstat.us/200").body).to eq("abc")
114
114
  end
115
115
 
116
116
  # WARNING: this makes a real HTTP request!
117
117
  it "should make a real request to allowed host", net_connect: true do
118
- expect(http_request(:get, "http://httpstat.us/200").status).to eq('200')
118
+ expect(http_request(:get, "https://httpstat.us/200").status).to eq('200')
119
119
  end
120
120
  end
121
121
  end
@@ -229,13 +229,13 @@ shared_context "allowing and disabling net connect" do |*adapter_info|
229
229
 
230
230
  context "when the host is allowed" do
231
231
  it "should return stubbed response if request was stubbed" do
232
- stub_request(:get, 'httpstat.us/200').to_return(body: "abc")
233
- expect(http_request(:get, "http://httpstat.us/200").body).to eq("abc")
232
+ stub_request(:get, 'https://httpstat.us/200').to_return(body: "abc")
233
+ expect(http_request(:get, "https://httpstat.us/200").body).to eq("abc")
234
234
  end
235
235
 
236
236
  # WARNING: this makes a real HTTP request!
237
237
  it "should make a real request to allowed host", net_connect: true do
238
- expect(http_request(:get, "http://httpstat.us/200").status).to eq('200')
238
+ expect(http_request(:get, "https://httpstat.us/200").status).to eq('200')
239
239
  end
240
240
 
241
241
  it "should make a real request if request is allowed by path regexp and url contains default port", net_connect: true do
@@ -266,20 +266,20 @@ shared_context "allowing and disabling net connect" do |*adapter_info|
266
266
 
267
267
  context "when the host is allowed" do
268
268
  it "should return stubbed response if request was stubbed" do
269
- stub_request(:get, 'httpstat.us/200').to_return(body: "abc")
270
- expect(http_request(:get, "http://httpstat.us/200").body).to eq("abc")
269
+ stub_request(:get, 'https://httpstat.us/200').to_return(body: "abc")
270
+ expect(http_request(:get, "https://httpstat.us/200").body).to eq("abc")
271
271
  end
272
272
 
273
273
  # WARNING: this makes a real HTTP request!
274
274
  it "should make a real request to allowed host", net_connect: true do
275
- expect(http_request(:get, "http://httpstat.us/200").status).to eq('200')
275
+ expect(http_request(:get, "https://httpstat.us/200").status).to eq('200')
276
276
  end
277
277
  end
278
278
  end
279
279
 
280
280
  describe "allowing by a list of the above" do
281
281
  before :each do
282
- WebMock.disable_net_connect!(allow: [lambda{|_| false }, %r{foobar}, 'httpstat.us'])
282
+ WebMock.disable_net_connect!(allow: [lambda{|_| false }, %r{foobar}, 'https://httpstat.us'])
283
283
  end
284
284
 
285
285
  context "when the host is not allowed" do
@@ -297,13 +297,13 @@ shared_context "allowing and disabling net connect" do |*adapter_info|
297
297
 
298
298
  context "when the host is allowed" do
299
299
  it "should return stubbed response if request was stubbed" do
300
- stub_request(:get, 'httpstat.us/200').to_return(body: "abc")
301
- expect(http_request(:get, "http://httpstat.us/200").body).to eq("abc")
300
+ stub_request(:get, 'https://httpstat.us/200').to_return(body: "abc")
301
+ expect(http_request(:get, "https://httpstat.us/200").body).to eq("abc")
302
302
  end
303
303
 
304
304
  # WARNING: this makes a real HTTP request!
305
305
  it "should make a real request to allowed host", net_connect: true do
306
- expect(http_request(:get, "http://httpstat.us/200").status).to eq('200')
306
+ expect(http_request(:get, "https://httpstat.us/200").status).to eq('200')
307
307
  end
308
308
  end
309
309
  end
@@ -102,7 +102,7 @@ shared_context "callbacks" do |*adapter_info|
102
102
  WebMock.after_request(except: [:other_lib]) do |_, response|
103
103
  @response = response
104
104
  end
105
- http_request(:get, "http://httpstat.us/201", headers: { "Accept" => "*" })
105
+ http_request(:get, "https://httpstat.us/201", headers: { "Accept" => "*" })
106
106
  end
107
107
 
108
108
  it "should pass real response to callback with status and message" do
@@ -111,7 +111,7 @@ shared_context "callbacks" do |*adapter_info|
111
111
  end
112
112
 
113
113
  it "should pass real response to callback with headers" do
114
- expect(@response.headers["X-Powered-By"]).to eq( "ASP.NET")
114
+ expect(@response.headers["Server"]).to eq( "Kestrel")
115
115
  expect(@response.headers["Content-Length"]).to eq("11") unless adapter_info.include?(:no_content_length_header)
116
116
  end
117
117
 
@@ -18,7 +18,7 @@ shared_context "complex cross-concern behaviors" do |*adapter_info|
18
18
  expect(played_back_response).to eq(real_response)
19
19
  end
20
20
 
21
- let(:no_content_url) { 'http://httpstat.us/204' }
21
+ let(:no_content_url) { 'https://httpstat.us/204' }
22
22
  [nil, ''].each do |stub_val|
23
23
  it "returns the same value (nil or "") for a request stubbed as #{stub_val.inspect} that a real empty response has", net_connect: true do
24
24
  unless http_library == :curb
@@ -593,6 +593,23 @@ shared_examples_for "stubbing requests" do |*adapter_info|
593
593
  end
594
594
  end
595
595
  end
596
+
597
+ context "when global stub should be invoked last" do
598
+ before do
599
+ WebMock.globally_stub_request(:after_local_stubs) do
600
+ { body: "global stub body" }
601
+ end
602
+ end
603
+
604
+ it "uses global stub when non-global stub is not defined" do
605
+ expect(http_request(:get, "http://www.example.com/").body).to eq("global stub body")
606
+ end
607
+
608
+ it "uses non-global stub first" do
609
+ stub_request(:get, "www.example.com").to_return(body: 'non-global stub body')
610
+ expect(http_request(:get, "http://www.example.com/").body).to eq("non-global stub body")
611
+ end
612
+ end
596
613
  end
597
614
 
598
615
  describe "when stubbing request with a block evaluated on request" do