webmock 3.8.3 → 3.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/CI.yml +37 -0
  3. data/CHANGELOG.md +132 -0
  4. data/Gemfile +1 -1
  5. data/README.md +70 -30
  6. data/Rakefile +12 -2
  7. data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +7 -5
  8. data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +6 -3
  9. data/lib/webmock/http_lib_adapters/http_rb/client.rb +4 -1
  10. data/lib/webmock/http_lib_adapters/http_rb/response.rb +13 -2
  11. data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +1 -1
  12. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +23 -6
  13. data/lib/webmock/http_lib_adapters/manticore_adapter.rb +8 -1
  14. data/lib/webmock/http_lib_adapters/net_http.rb +17 -3
  15. data/lib/webmock/request_pattern.rb +77 -46
  16. data/lib/webmock/response.rb +11 -5
  17. data/lib/webmock/rspec.rb +2 -1
  18. data/lib/webmock/stub_registry.rb +26 -11
  19. data/lib/webmock/test_unit.rb +1 -3
  20. data/lib/webmock/version.rb +1 -1
  21. data/lib/webmock/webmock.rb +5 -3
  22. data/spec/acceptance/async_http_client/async_http_client_spec.rb +27 -1
  23. data/spec/acceptance/em_http_request/em_http_request_spec.rb +56 -0
  24. data/spec/acceptance/manticore/manticore_spec.rb +32 -0
  25. data/spec/acceptance/net_http/net_http_spec.rb +38 -0
  26. data/spec/acceptance/patron/patron_spec_helper.rb +2 -2
  27. data/spec/acceptance/shared/stubbing_requests.rb +35 -0
  28. data/spec/unit/request_pattern_spec.rb +171 -48
  29. data/spec/unit/response_spec.rb +22 -18
  30. data/spec/unit/webmock_spec.rb +52 -11
  31. data/test/test_webmock.rb +6 -0
  32. data/webmock.gemspec +2 -1
  33. metadata +25 -11
  34. data/.travis.yml +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c101b3661b9aeb49e30e85da73705637944747d62eef4d463a9c30866431b10
4
- data.tar.gz: 3c2a7ae9e28143b97b83c5a93cc14950748dc68969790d80f0d62a28600d7a5a
3
+ metadata.gz: a8f150fbeccca419468dfebe632e3b5d365cb8c2df9a5e2a31e65591298786fb
4
+ data.tar.gz: d92950bc5ae3510e599c40545f3e7a0ebaafa54a698f79a3c82243e240d35948
5
5
  SHA512:
6
- metadata.gz: 60174ed92a21c2f304d29e4d00edb7447eae871b37ddc2bb6b0a4704bf42492c9632913cee2c040644e6decc95242f39bf32728fe0df3b34d936cc9f78a42f2f
7
- data.tar.gz: e7c4dc5363ec3f8028852b1d2173b214742bc03ca2ee25599a6d38d8c3a291f517890168dc74a69cd4f90f3f840e94fdd857941ab853a833ae5d77bc8282e464
6
+ metadata.gz: f58d569f7c633d758cee725e5dafb39edacb74e0017ba9c29de0cad8fe16d1f7740cc30847a9f129f6571232d2ca8172d7fb76a1eb3383e31ee8371472f141f9
7
+ data.tar.gz: 52191c4e12ac3bf79b575f36d58823ea37ab17f83c7a62602889f361eafadabfa4b0b8ffc1f466eee6de53ea77578fc0149a60e14abdd8a7459b651afbeb85d0
@@ -0,0 +1,37 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ ruby:
16
+ - head
17
+ - '3.0'
18
+ - '2.7'
19
+ - '2.6'
20
+ - '2.5'
21
+ - jruby
22
+ continue-on-error: ${{ matrix.ruby == 'head' }}
23
+ name: Ruby ${{ matrix.ruby }}
24
+ env:
25
+ JRUBY_OPTS: "--debug"
26
+ steps:
27
+ - uses: actions/checkout@v2
28
+ - name: Install Apt Packages
29
+ run: |
30
+ sudo apt-get install libcurl4-openssl-dev -y
31
+ - uses: ruby/setup-ruby@v1
32
+ continue-on-error: true
33
+ with:
34
+ ruby-version: ${{ matrix.ruby }}
35
+ bundler-cache: true
36
+ - run: |
37
+ bundle exec rake
data/CHANGELOG.md CHANGED
@@ -1,5 +1,137 @@
1
1
  # Changelog
2
2
 
3
+ # 3.14.0
4
+
5
+ * Bump Addressable from 2.3.6 to 2.8.0
6
+
7
+ Thanks to [Eduardo Hernandez](https://github.com/EduardoGHdez)
8
+
9
+ # 3.13.0
10
+
11
+ * Support http.rb 5.x
12
+
13
+ Thanks to [Will Storey](https://github.com/horgh)
14
+
15
+ # 3.12.2
16
+
17
+ * Fixed em-http-request adapter to avoid calling middleware twice.
18
+
19
+ Thanks to [Alex Vondrak](https://github.com/ajvondrak)
20
+
21
+ # 3.12.1
22
+
23
+ * Fixed handling of URIs with IPv6 addresses with square brackets when in Net::HTTP adapter.
24
+
25
+ Thanks to [Johanna Hartmann](https://github.com/JohannaHartmann)
26
+
27
+ # 3.12.0
28
+
29
+ * Added support for handling custom JSON and XML content types e.g. 'application/vnd.api+json'
30
+
31
+ # 3.11.3
32
+
33
+ * Fixed async-http adapter to only considered requests as real if they are real.
34
+
35
+ Thanks to Thanks to [Tony Schneider](https://github.com/tonywok) and [Samuel Williams](https://github.com/ioquatix)
36
+
37
+ # 3.11.2
38
+
39
+ * Fix for Manticore streaming mode
40
+
41
+ Thanks to [Oleksiy Kovyrin](https://github.com/kovyrin)
42
+
43
+ # 3.11.1
44
+
45
+ * Compatibility with async-http 0.54+
46
+
47
+ Thanks to [Jun Jiang](https://github.com/jasl)
48
+
49
+ # 3.11.0
50
+
51
+ * Added support for `features` in http.rb adapter.
52
+
53
+ Thanks to [Carl (ce07c3)](https://github.com/ce07c3)
54
+
55
+ # 3.10.0
56
+
57
+ * Added option to global stubs to have lower priority than local stubs.
58
+
59
+ WebMock.globally_stub_request(:after_local_stubs) do
60
+ { body: "global stub body" }
61
+ end
62
+
63
+ stub_request(:get, "www.example.com").to_return(body: 'non-global stub body')
64
+
65
+ expect(http_request(:get, "http://www.example.com/").body).to eq("non-global stub body")
66
+
67
+ Thanks to [Marek Kasztelnik](https://github.com/mkasztelnik)
68
+
69
+ # 3.9.5
70
+
71
+ * Prevent overwriting `teardown` method in Test::Unit
72
+
73
+ Thanks to [Jesse Bowes](https://github.com/jessebs)
74
+
75
+ # 3.9.4
76
+
77
+ * More intuitive error message when stubbed response body was provided as Hash
78
+
79
+ Thanks to [Ben Koshy](https://github.com/BKSpurgeon)
80
+
81
+ # 3.9.3
82
+
83
+ * Make httpclient_adapter thread-safe
84
+
85
+ Thanks to [Adam Harwood](https://github.com/adam-harwood)
86
+
87
+ # 3.9.2
88
+
89
+ * Made global stubs thread-safe
90
+
91
+ Thanks to [Adam Harwood](https://github.com/adam-harwood)
92
+
93
+ # 3.9.1
94
+
95
+ * Fixed support for passing `URI` objects as second argument of `stub_request`
96
+
97
+ Thanks to [Ryan Kerr](https://github.com/leboshi)
98
+
99
+ ## 3.9.0
100
+
101
+ * Allow using a "callable" (like a proc) as URI pattern
102
+
103
+ stub_request(:any, ->(uri) { true })
104
+
105
+ Thanks to [John Hawthorn](https://github.com/jhawthorn)
106
+
107
+ * Added stubbed IO on stubbed socket in Net::HTTP adapter.
108
+
109
+ Thanks to [Thilo Rusche](https://github.com/trusche)
110
+
111
+ * When 'webmock/rspec' is required, reset WebMock after all after(:each/example) hooks
112
+
113
+ Thanks to [Andrew Stuntz](https://github.com/drews256)
114
+
115
+ * Fixed `net_connect_allowed?` when invoked with no arguments, when there were any allowed URIs passed to `disable_net_connect?`.
116
+
117
+ Thanks to [Lucas Uyezu](https://github.com/lucasuyezu)
118
+
119
+ * Fixed async-http adapter which caused Async::HTTP::Client or Async::HTTP::Internet to hang and never return a response.
120
+
121
+ Thanks to [Bruno Sutic](https://github.com/bruno-) and [Samuel Williams](https://github.com/ioquatix)
122
+
123
+ * Fixed warning when using async-http adapter
124
+
125
+ Thanks to [Bruno Sutic](https://github.com/bruno-)
126
+
127
+ * Dropped support for Ruby 2.3 - EOL date: 2019-03-31
128
+
129
+ * Dropped support for Ruby 2.4 - EOL date: 2020-03-31
130
+
131
+ * Handling matching of Addressable::Template patterns that have an ip address without port and patterns that have ip address and don’t have schema and path.
132
+
133
+ Thanks to [Rafael França](https://github.com/rafaelfranca) and [guppy0356](https://github.com/guppy0356)
134
+
3
135
  ## 3.8.3
4
136
 
5
137
  * Fixed problem introduced in version 3.4.2, which caused matching against Addressable::Template representing host part of the URI to raise an error.
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'http://rubygems.org/'
1
+ source 'https://rubygems.org/'
2
2
 
3
3
  gemspec
4
4
 
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  WebMock
2
2
  =======
3
3
  [![Gem Version](https://badge.fury.io/rb/webmock.svg)](http://badge.fury.io/rb/webmock)
4
- [![Build Status](https://secure.travis-ci.org/bblimke/webmock.svg?branch=master)](http://travis-ci.org/bblimke/webmock)
4
+ [![Build Status](https://github.com/bblimke/webmock/workflows/CI/badge.svg?branch=master)](https://github.com/bblimke/webmock/actions)
5
5
  [![Code Climate](https://codeclimate.com/github/bblimke/webmock/badges/gpa.svg)](https://codeclimate.com/github/bblimke/webmock)
6
6
  [![Mentioned in Awesome Ruby](https://awesome.re/mentioned-badge.svg)](https://github.com/markets/awesome-ruby)
7
7
  [![Inline docs](http://inch-ci.org/github/bblimke/webmock.svg?branch=master)](http://inch-ci.org/github/bblimke/webmock)
@@ -24,23 +24,23 @@ Features
24
24
  Supported HTTP libraries
25
25
  ------------------------
26
26
 
27
- * Net::HTTP and libraries based on Net::HTTP (i.e RightHttpConnection, REST Client, HTTParty)
28
- * HTTPClient
29
- * Patron
30
- * EM-HTTP-Request
31
- * Curb (currently only Curb::Easy)
32
- * Typhoeus (currently only Typhoeus::Hydra)
33
- * Excon
34
- * HTTP Gem
35
- * Manticore
36
- * Async::HTTP::Client
27
+ * [Async::HTTP::Client](https://github.com/socketry/async-http)
28
+ * [Curb](https://github.com/taf2/curb) (currently only Curb::Easy)
29
+ * [EM-HTTP-Request](https://github.com/igrigorik/em-http-request)
30
+ * [Excon](https://github.com/excon/excon)
31
+ * [HTTPClient](https://github.com/nahi/httpclient)
32
+ * [HTTP Gem (also known as http.rb)](https://github.com/httprb/http)
33
+ * [httpx](https://honeyryderchuck.gitlab.io/httpx/wiki/Webmock-Adapter)
34
+ * [Manticore](https://github.com/cheald/manticore)
35
+ * [Net::HTTP](https://ruby-doc.org/stdlib-2.7.0/libdoc/net/http/rdoc/Net/HTTP.html) and other libraries based on Net::HTTP, e.g.:
36
+ * [HTTParty](https://github.com/jnunemaker/httparty)
37
+ * [REST Client](https://github.com/rest-client/rest-client)
38
+ * [Patron](https://github.com/toland/patron)
39
+ * [Typhoeus](https://github.com/typhoeus/typhoeus) (currently only Typhoeus::Hydra)
37
40
 
38
41
  Supported Ruby Interpreters
39
42
  ---------------------------
40
43
 
41
- * MRI 2.2
42
- * MRI 2.3
43
- * MRI 2.4
44
44
  * MRI 2.5
45
45
  * MRI 2.6
46
46
  * MRI 2.7
@@ -49,7 +49,17 @@ Supported Ruby Interpreters
49
49
 
50
50
  ## Installation
51
51
 
52
+ ```bash
52
53
  gem install webmock
54
+ ```
55
+ or alternatively:
56
+
57
+ ```ruby
58
+ # add to your Gemfile
59
+ group :test do
60
+ gem "webmock"
61
+ end
62
+ ```
53
63
 
54
64
  ### or to install the latest development version from github master
55
65
 
@@ -61,36 +71,36 @@ Supported Ruby Interpreters
61
71
 
62
72
  WebMock 2.x has changed somewhat since version 1.x. Changes are listed in [CHANGELOG.md](CHANGELOG.md)
63
73
 
64
- ### Test::Unit
74
+ ### Cucumber
65
75
 
66
- Add the following code to `test/test_helper.rb`
76
+ Create a file `features/support/webmock.rb` with the following contents:
67
77
 
68
78
  ```ruby
69
- require 'webmock/test_unit'
79
+ require 'webmock/cucumber'
70
80
  ```
71
81
 
72
- ### RSpec
82
+ ### MiniTest
73
83
 
74
- Add the following code to `spec/spec_helper`:
84
+ Add the following code to `test/test_helper`:
75
85
 
76
86
  ```ruby
77
- require 'webmock/rspec'
87
+ require 'webmock/minitest'
78
88
  ```
79
89
 
80
- ### MiniTest
90
+ ### RSpec
81
91
 
82
- Add the following code to `test/test_helper`:
92
+ Add the following code to `spec/spec_helper`:
83
93
 
84
94
  ```ruby
85
- require 'webmock/minitest'
95
+ require 'webmock/rspec'
86
96
  ```
87
97
 
88
- ### Cucumber
98
+ ### Test::Unit
89
99
 
90
- Create a file `features/support/webmock.rb` with the following contents:
100
+ Add the following code to `test/test_helper.rb`
91
101
 
92
102
  ```ruby
93
- require 'webmock/cucumber'
103
+ require 'webmock/test_unit'
94
104
  ```
95
105
 
96
106
  ### Outside a test framework
@@ -104,13 +114,10 @@ include WebMock::API
104
114
  WebMock.enable!
105
115
  ```
106
116
 
107
- ## Examples
108
-
109
-
117
+ # Examples
110
118
 
111
119
  ## Stubbing
112
120
 
113
-
114
121
  ### Stubbed request based on uri only and with the default response
115
122
 
116
123
  ```ruby
@@ -243,6 +250,12 @@ stub_request(:any, /example/)
243
250
  Net::HTTP.get('www.example.com', '/') # ===> Success
244
251
  ```
245
252
 
253
+ ### Matching uris using lambda
254
+
255
+ ```ruby
256
+ stub_request(:any, ->(uri) { true })
257
+ ```
258
+
246
259
  ### Matching uris using RFC 6570 - Basic Example
247
260
 
248
261
  ```ruby
@@ -300,6 +313,12 @@ stub_request(:any, "www.example.com").
300
313
  Net::HTTP.get("www.example.com", '/') # ===> "abc"
301
314
  ```
302
315
 
316
+ Set appropriate Content-Type for HTTParty's `parsed_response`.
317
+
318
+ ```ruby
319
+ stub_request(:any, "www.example.com").to_return body: '{}', headers: {content_type: 'application/json'}
320
+ ```
321
+
303
322
  ### Response with body specified as IO object
304
323
 
305
324
  ```ruby
@@ -1121,6 +1140,27 @@ People who submitted patches and new features or suggested improvements. Many th
1121
1140
  * Patrik Ragnarsson
1122
1141
  * Alex Coomans
1123
1142
  * Vesa Laakso
1143
+ * John Hawthorn
1144
+ * guppy0356
1145
+ * Thilo Rusche
1146
+ * Andrew Stuntz
1147
+ * Lucas Uyezu
1148
+ * Bruno Sutic
1149
+ * Ryan Kerr
1150
+ * Adam Harwood
1151
+ * Ben Koshy
1152
+ * Jesse Bowes
1153
+ * Marek Kasztelnik
1154
+ * ce07c3
1155
+ * Jun Jiang
1156
+ * Oleksiy Kovyrin
1157
+ * Matt Larraz
1158
+ * Tony Schneider
1159
+ * Niklas Hösl
1160
+ * Johanna Hartmann
1161
+ * Alex Vondrak
1162
+ * Will Storey
1163
+ * Eduardo Hernandez
1124
1164
 
1125
1165
  For a full list of contributors you can visit the
1126
1166
  [contributors](https://github.com/bblimke/webmock/contributors) page.
data/Rakefile CHANGED
@@ -3,24 +3,34 @@ Bundler::GemHelper.install_tasks
3
3
 
4
4
  require "rspec/core/rake_task"
5
5
  RSpec::Core::RakeTask.new(:spec) do |t|
6
- t.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
6
+ t.rspec_opts = %w[
7
+ --force-color
8
+ --format progress
9
+ --require ./spec/spec_helper.rb
10
+ ]
7
11
  t.pattern = 'spec/**/*_spec.rb'
8
12
  end
9
13
 
10
14
  RSpec::Core::RakeTask.new(:spec_http_without_webmock) do |t|
11
- t.rspec_opts = ["-c", "-f progress", "-r ./spec/acceptance/net_http/real_net_http_spec.rb"]
15
+ t.rspec_opts = %w[
16
+ --force-color
17
+ --format progress
18
+ --require ./spec/acceptance/net_http/real_net_http_spec.rb
19
+ ]
12
20
  t.pattern = 'spec/acceptance/net_http/real_net_http_spec.rb'
13
21
  end
14
22
 
15
23
  require 'rake/testtask'
16
24
  Rake::TestTask.new(:test) do |test|
17
25
  test.test_files = FileList["test/**/*.rb"].exclude("test/test_helper.rb")
26
+ test.options = "--use-color"
18
27
  test.verbose = false
19
28
  test.warning = false
20
29
  end
21
30
 
22
31
  Rake::TestTask.new(:minitest) do |test|
23
32
  test.test_files = FileList["minitest/**/*.rb"].exclude("test/test_helper.rb")
33
+ test.options = "--pride"
24
34
  test.verbose = false
25
35
  test.warning = false
26
36
  end
@@ -40,8 +40,8 @@ if defined?(Async::HTTP)
40
40
  )
41
41
  webmock_endpoint = WebMockEndpoint.new(scheme, authority, protocol)
42
42
 
43
- @network_client = WebMockClient.new(endpoint, protocol, scheme, authority, **options)
44
- @webmock_client = WebMockClient.new(webmock_endpoint, protocol, scheme, authority, **options)
43
+ @network_client = WebMockClient.new(endpoint, **options)
44
+ @webmock_client = WebMockClient.new(webmock_endpoint, **options)
45
45
 
46
46
  @scheme = scheme
47
47
  @authority = authority
@@ -55,6 +55,7 @@ if defined?(Async::HTTP)
55
55
  WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
56
56
  webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
57
57
  net_connect_allowed = WebMock.net_connect_allowed?(request_signature.uri)
58
+ real_request = false
58
59
 
59
60
  if webmock_response
60
61
  webmock_response.raise_error_if_any
@@ -63,6 +64,7 @@ if defined?(Async::HTTP)
63
64
  response = @webmock_client.call(request)
64
65
  elsif net_connect_allowed
65
66
  response = @network_client.call(request)
67
+ real_request = true
66
68
  else
67
69
  raise WebMock::NetConnectNotAllowedError.new(request_signature) unless webmock_response
68
70
  end
@@ -72,7 +74,7 @@ if defined?(Async::HTTP)
72
74
  WebMock::CallbackRegistry.invoke_callbacks(
73
75
  {
74
76
  lib: :async_http_client,
75
- real_request: net_connect_allowed
77
+ real_request: real_request
76
78
  },
77
79
  request_signature,
78
80
  webmock_response
@@ -136,7 +138,7 @@ if defined?(Async::HTTP)
136
138
 
137
139
  def connect
138
140
  server_socket, client_socket = create_connected_sockets
139
- Async do
141
+ Async(transient: true) do
140
142
  accept_socket(server_socket)
141
143
  end
142
144
  client_socket
@@ -151,7 +153,7 @@ if defined?(Async::HTTP)
151
153
  def create_connected_sockets
152
154
  Async::IO::Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM).tap do |sockets|
153
155
  sockets.each do |socket|
154
- socket.instance_variable_set :@alpn_protocol, @alpn_protocol
156
+ socket.instance_variable_set :@alpn_protocol, nil
155
157
  socket.instance_eval do
156
158
  def alpn_protocol
157
159
  nil # means HTTP11 will be used for HTTPS
@@ -99,6 +99,11 @@ if defined?(EventMachine::HttpClient)
99
99
  end
100
100
  end
101
101
 
102
+ def connection_completed
103
+ @state = :response_header
104
+ send_request(request_signature.headers, request_signature.body)
105
+ end
106
+
102
107
  def send_request(head, body)
103
108
  WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
104
109
 
@@ -164,7 +169,7 @@ if defined?(EventMachine::HttpClient)
164
169
  end
165
170
 
166
171
  def build_request_signature
167
- headers, body = @req.headers, @req.body
172
+ headers, body = build_request, @req.body
168
173
 
169
174
  @conn.middleware.select {|m| m.respond_to?(:request) }.each do |m|
170
175
  headers, body = m.request(self, headers, body)
@@ -178,8 +183,6 @@ if defined?(EventMachine::HttpClient)
178
183
 
179
184
  body = form_encode_body(body) if body.is_a?(Hash)
180
185
 
181
- headers = @req.headers
182
-
183
186
  if headers['authorization'] && headers['authorization'].is_a?(Array)
184
187
  headers['Authorization'] = WebMock::Util::Headers.basic_auth_header(headers.delete('authorization'))
185
188
  end
@@ -4,7 +4,10 @@ module HTTP
4
4
 
5
5
  def perform(request, options)
6
6
  return __perform__(request, options) unless webmock_enabled?
7
- WebMockPerform.new(request) { __perform__(request, options) }.exec
7
+
8
+ response = WebMockPerform.new(request) { __perform__(request, options) }.exec
9
+ options.features.each { |_name, feature| response = feature.wrap_response(response) }
10
+ response
8
11
  end
9
12
 
10
13
  def webmock_enabled?
@@ -11,7 +11,7 @@ module HTTP
11
11
  end
12
12
 
13
13
  class << self
14
- def from_webmock(webmock_response, request_signature = nil)
14
+ def from_webmock(request, webmock_response, request_signature = nil)
15
15
  status = Status.new(webmock_response.status.first)
16
16
  headers = webmock_response.headers || {}
17
17
  uri = normalize_uri(request_signature && request_signature.uri)
@@ -29,12 +29,23 @@ module HTTP
29
29
 
30
30
  return new(status, "1.1", headers, body, uri) if HTTP::VERSION < "1.0.0"
31
31
 
32
+ # 5.0.0 had a breaking change to require request instead of uri.
33
+ if HTTP::VERSION < '5.0.0'
34
+ return new({
35
+ status: status,
36
+ version: "1.1",
37
+ headers: headers,
38
+ body: body,
39
+ uri: uri
40
+ })
41
+ end
42
+
32
43
  new({
33
44
  status: status,
34
45
  version: "1.1",
35
46
  headers: headers,
36
47
  body: body,
37
- uri: uri
48
+ request: request,
38
49
  })
39
50
  end
40
51
 
@@ -38,7 +38,7 @@ module HTTP
38
38
  webmock_response.raise_error_if_any
39
39
 
40
40
  invoke_callbacks(webmock_response, real_request: false)
41
- ::HTTP::Response.from_webmock webmock_response, request_signature
41
+ ::HTTP::Response.from_webmock @request, webmock_response, request_signature
42
42
  end
43
43
 
44
44
  def raise_timeout_error
@@ -43,6 +43,9 @@ if defined?(::HTTPClient)
43
43
  end
44
44
 
45
45
  module WebMockHTTPClients
46
+
47
+ REQUEST_RESPONSE_LOCK = Mutex.new
48
+
46
49
  def do_get_block(req, proxy, conn, &block)
47
50
  do_get(req, proxy, conn, false, &block)
48
51
  end
@@ -57,7 +60,7 @@ if defined?(::HTTPClient)
57
60
  WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
58
61
 
59
62
  if webmock_responses[request_signature]
60
- webmock_response = webmock_responses.delete(request_signature)
63
+ webmock_response = synchronize_request_response { webmock_responses.delete(request_signature) }
61
64
  response = build_httpclient_response(webmock_response, stream, req.header, &block)
62
65
  @request_filter.each do |filter|
63
66
  filter.filter_response(req, response)
@@ -68,7 +71,7 @@ if defined?(::HTTPClient)
68
71
  res
69
72
  elsif WebMock.net_connect_allowed?(request_signature.uri)
70
73
  # in case there is a nil entry in the hash...
71
- webmock_responses.delete(request_signature)
74
+ synchronize_request_response { webmock_responses.delete(request_signature) }
72
75
 
73
76
  res = if stream
74
77
  do_get_stream_without_webmock(req, proxy, conn, &block)
@@ -100,7 +103,7 @@ if defined?(::HTTPClient)
100
103
  def do_request_async(method, uri, query, body, extheader)
101
104
  req = create_request(method, uri, query, body, extheader)
102
105
  request_signature = build_request_signature(req)
103
- webmock_request_signatures << request_signature
106
+ synchronize_request_response { webmock_request_signatures << request_signature }
104
107
 
105
108
  if webmock_responses[request_signature] || WebMock.net_connect_allowed?(request_signature.uri)
106
109
  super
@@ -184,7 +187,9 @@ if defined?(::HTTPClient)
184
187
 
185
188
  def webmock_responses
186
189
  @webmock_responses ||= Hash.new do |hash, request_signature|
187
- hash[request_signature] = WebMock::StubRegistry.instance.response_for_request(request_signature)
190
+ synchronize_request_response do
191
+ hash[request_signature] = WebMock::StubRegistry.instance.response_for_request(request_signature)
192
+ end
188
193
  end
189
194
  end
190
195
 
@@ -193,8 +198,10 @@ if defined?(::HTTPClient)
193
198
  end
194
199
 
195
200
  def previous_signature_for(signature)
196
- return nil unless index = webmock_request_signatures.index(signature)
197
- webmock_request_signatures.delete_at(index)
201
+ synchronize_request_response do
202
+ return nil unless index = webmock_request_signatures.index(signature)
203
+ webmock_request_signatures.delete_at(index)
204
+ end
198
205
  end
199
206
 
200
207
  private
@@ -209,6 +216,16 @@ if defined?(::HTTPClient)
209
216
  hdrs
210
217
  end
211
218
  end
219
+
220
+ def synchronize_request_response
221
+ if REQUEST_RESPONSE_LOCK.owned?
222
+ yield
223
+ else
224
+ REQUEST_RESPONSE_LOCK.synchronize do
225
+ yield
226
+ end
227
+ end
228
+ end
212
229
  end
213
230
 
214
231
  class WebMockHTTPClient < HTTPClient
@@ -127,8 +127,15 @@ if defined?(Manticore)
127
127
  def generate_webmock_response(manticore_response)
128
128
  webmock_response = WebMock::Response.new
129
129
  webmock_response.status = [manticore_response.code, manticore_response.message]
130
- webmock_response.body = manticore_response.body
131
130
  webmock_response.headers = manticore_response.headers
131
+
132
+ # The attempt to read the body could fail if manticore is used in a streaming mode
133
+ webmock_response.body = begin
134
+ manticore_response.body
135
+ rescue ::Manticore::StreamClosedException
136
+ nil
137
+ end
138
+
132
139
  webmock_response
133
140
  end
134
141
  end