webmock 3.5.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 +476 -2
- data/README.md +166 -42
- 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 +228 -0
- data/lib/webmock/http_lib_adapters/curb_adapter.rb +14 -3
- data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +22 -9
- data/lib/webmock/http_lib_adapters/excon_adapter.rb +5 -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 +4 -1
- data/lib/webmock/http_lib_adapters/http_rb/request.rb +17 -5
- data/lib/webmock/http_lib_adapters/http_rb/response.rb +49 -5
- data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +11 -3
- 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 +25 -7
- data/lib/webmock/http_lib_adapters/manticore_adapter.rb +35 -15
- data/lib/webmock/http_lib_adapters/net_http.rb +59 -112
- data/lib/webmock/http_lib_adapters/net_http_response.rb +3 -1
- data/lib/webmock/http_lib_adapters/patron_adapter.rb +4 -2
- 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 +3 -1
- data/lib/webmock/request_execution_verifier.rb +2 -0
- data/lib/webmock/request_pattern.rb +118 -61
- 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 +22 -14
- data/lib/webmock/responses_sequence.rb +2 -0
- data/lib/webmock/rspec/matchers/request_pattern_matcher.rb +2 -0
- data/lib/webmock/rspec/matchers/webmock_matcher.rb +2 -0
- data/lib/webmock/rspec/matchers.rb +2 -0
- data/lib/webmock/rspec.rb +4 -1
- data/lib/webmock/stub_registry.rb +28 -11
- data/lib/webmock/stub_request_snippet.rb +2 -0
- data/lib/webmock/test_unit.rb +3 -3
- 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 +6 -2
- data/lib/webmock/util/uri.rb +11 -9
- 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 +22 -3
- data/lib/webmock.rb +5 -2
- metadata +99 -175
- data/.gemtest +0 -0
- data/.gitignore +0 -34
- data/.rspec-tm +0 -2
- data/.travis.yml +0 -21
- data/Gemfile +0 -9
- data/Rakefile +0 -30
- 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/curb/curb_spec.rb +0 -481
- data/spec/acceptance/curb/curb_spec_helper.rb +0 -147
- data/spec/acceptance/em_http_request/em_http_request_spec.rb +0 -406
- data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +0 -77
- data/spec/acceptance/excon/excon_spec.rb +0 -77
- data/spec/acceptance/excon/excon_spec_helper.rb +0 -50
- data/spec/acceptance/http_rb/http_rb_spec.rb +0 -82
- 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 -56
- data/spec/acceptance/manticore/manticore_spec_helper.rb +0 -35
- data/spec/acceptance/net_http/net_http_shared.rb +0 -153
- data/spec/acceptance/net_http/net_http_spec.rb +0 -331
- 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 -147
- data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +0 -36
- data/spec/acceptance/shared/enabling_and_disabling_webmock.rb +0 -95
- data/spec/acceptance/shared/precedence_of_stubs.rb +0 -15
- data/spec/acceptance/shared/request_expectations.rb +0 -923
- data/spec/acceptance/shared/returning_declared_responses.rb +0 -388
- data/spec/acceptance/shared/stubbing_requests.rb +0 -638
- data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +0 -135
- data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +0 -60
- data/spec/acceptance/webmock_shared.rb +0 -41
- data/spec/fixtures/test.txt +0 -1
- data/spec/quality_spec.rb +0 -84
- data/spec/spec_helper.rb +0 -48
- data/spec/support/example_curl_output.txt +0 -22
- data/spec/support/failures.rb +0 -9
- data/spec/support/my_rack_app.rb +0 -53
- data/spec/support/network_connection.rb +0 -19
- data/spec/support/webmock_server.rb +0 -69
- data/spec/unit/api_spec.rb +0 -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 -596
- data/spec/unit/request_registry_spec.rb +0 -95
- data/spec/unit/request_signature_snippet_spec.rb +0 -89
- data/spec/unit/request_signature_spec.rb +0 -155
- data/spec/unit/request_stub_spec.rb +0 -199
- data/spec/unit/response_spec.rb +0 -282
- data/spec/unit/stub_registry_spec.rb +0 -103
- data/spec/unit/stub_request_snippet_spec.rb +0 -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 -150
- data/spec/unit/util/uri_spec.rb +0 -299
- data/spec/unit/util/version_checker_spec.rb +0 -65
- data/spec/unit/webmock_spec.rb +0 -11
- data/test/http_request.rb +0 -24
- data/test/shared_test.rb +0 -108
- data/test/test_helper.rb +0 -23
- data/test/test_webmock.rb +0 -6
- data/webmock.gemspec +0 -46
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
WebMock
|
2
2
|
=======
|
3
|
-
[](http://badge.fury.io/rb/webmock)
|
3
|
+
[](http://badge.fury.io/rb/webmock)
|
4
|
+
[](https://github.com/bblimke/webmock/actions)
|
5
|
+
[](https://codeclimate.com/github/bblimke/webmock)
|
6
|
+
[](https://github.com/markets/awesome-ruby)
|
4
7
|
|
5
8
|
Library for stubbing and setting expectations on HTTP requests in Ruby.
|
6
9
|
|
@@ -19,70 +22,87 @@ Features
|
|
19
22
|
Supported HTTP libraries
|
20
23
|
------------------------
|
21
24
|
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
26
|
-
*
|
27
|
-
*
|
28
|
-
*
|
29
|
-
*
|
30
|
-
*
|
25
|
+
* [Async::HTTP::Client](https://github.com/socketry/async-http)
|
26
|
+
* [Curb](https://github.com/taf2/curb) (currently only Curb::Easy)
|
27
|
+
* [EM-HTTP-Request](https://github.com/igrigorik/em-http-request)
|
28
|
+
* [Excon](https://github.com/excon/excon)
|
29
|
+
* [HTTPClient](https://github.com/nahi/httpclient)
|
30
|
+
* [HTTP Gem (also known as http.rb)](https://github.com/httprb/http)
|
31
|
+
* [httpx](https://honeyryderchuck.gitlab.io/httpx/wiki/Webmock-Adapter)
|
32
|
+
* [Manticore](https://github.com/cheald/manticore)
|
33
|
+
* [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.:
|
34
|
+
* [HTTParty](https://github.com/jnunemaker/httparty)
|
35
|
+
* [REST Client](https://github.com/rest-client/rest-client)
|
36
|
+
* [Patron](https://github.com/toland/patron)
|
37
|
+
* [Typhoeus](https://github.com/typhoeus/typhoeus) (currently only Typhoeus::Hydra)
|
31
38
|
|
32
39
|
Supported Ruby Interpreters
|
33
40
|
---------------------------
|
34
|
-
|
35
|
-
* MRI 2.
|
36
|
-
* MRI
|
37
|
-
* MRI
|
38
|
-
* MRI 2
|
41
|
+
* MRI 2.6
|
42
|
+
* MRI 2.7
|
43
|
+
* MRI 3.0
|
44
|
+
* MRI 3.1
|
45
|
+
* MRI 3.2
|
46
|
+
* MRI 3.3
|
47
|
+
* MRI 3.4
|
39
48
|
* JRuby
|
40
|
-
* Rubinius
|
41
49
|
|
42
50
|
## Installation
|
43
51
|
|
44
|
-
|
52
|
+
```bash
|
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
|
+
```
|
45
63
|
|
46
64
|
### or to install the latest development version from github master
|
47
65
|
|
48
|
-
|
49
|
-
|
50
|
-
|
66
|
+
```bash
|
67
|
+
git clone http://github.com/bblimke/webmock.git
|
68
|
+
cd webmock
|
69
|
+
rake install
|
70
|
+
```
|
51
71
|
|
52
72
|
## Upgrading from v1.x to v2.x
|
53
73
|
|
54
74
|
WebMock 2.x has changed somewhat since version 1.x. Changes are listed in [CHANGELOG.md](CHANGELOG.md)
|
55
75
|
|
56
|
-
###
|
76
|
+
### Cucumber
|
57
77
|
|
58
|
-
|
78
|
+
Create a file `features/support/webmock.rb` with the following contents:
|
59
79
|
|
60
80
|
```ruby
|
61
|
-
require 'webmock/
|
81
|
+
require 'webmock/cucumber'
|
62
82
|
```
|
63
83
|
|
64
|
-
###
|
84
|
+
### MiniTest
|
65
85
|
|
66
|
-
Add the following code to `
|
86
|
+
Add the following code to `test/test_helper`:
|
67
87
|
|
68
88
|
```ruby
|
69
|
-
require 'webmock/
|
89
|
+
require 'webmock/minitest'
|
70
90
|
```
|
71
91
|
|
72
|
-
###
|
92
|
+
### RSpec
|
73
93
|
|
74
|
-
Add the following code to `
|
94
|
+
Add the following code to `spec/spec_helper`:
|
75
95
|
|
76
96
|
```ruby
|
77
|
-
require 'webmock/
|
97
|
+
require 'webmock/rspec'
|
78
98
|
```
|
79
99
|
|
80
|
-
###
|
100
|
+
### Test::Unit
|
81
101
|
|
82
|
-
|
102
|
+
Add the following code to `test/test_helper.rb`
|
83
103
|
|
84
104
|
```ruby
|
85
|
-
require 'webmock/
|
105
|
+
require 'webmock/test_unit'
|
86
106
|
```
|
87
107
|
|
88
108
|
### Outside a test framework
|
@@ -96,13 +116,10 @@ include WebMock::API
|
|
96
116
|
WebMock.enable!
|
97
117
|
```
|
98
118
|
|
99
|
-
|
100
|
-
|
101
|
-
|
119
|
+
# Examples
|
102
120
|
|
103
121
|
## Stubbing
|
104
122
|
|
105
|
-
|
106
123
|
### Stubbed request based on uri only and with the default response
|
107
124
|
|
108
125
|
```ruby
|
@@ -235,6 +252,12 @@ stub_request(:any, /example/)
|
|
235
252
|
Net::HTTP.get('www.example.com', '/') # ===> Success
|
236
253
|
```
|
237
254
|
|
255
|
+
### Matching uris using lambda
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
stub_request(:any, ->(uri) { true })
|
259
|
+
```
|
260
|
+
|
238
261
|
### Matching uris using RFC 6570 - Basic Example
|
239
262
|
|
240
263
|
```ruby
|
@@ -292,6 +315,12 @@ stub_request(:any, "www.example.com").
|
|
292
315
|
Net::HTTP.get("www.example.com", '/') # ===> "abc"
|
293
316
|
```
|
294
317
|
|
318
|
+
Set appropriate Content-Type for HTTParty's `parsed_response`.
|
319
|
+
|
320
|
+
```ruby
|
321
|
+
stub_request(:any, "www.example.com").to_return body: '{}', headers: {content_type: 'application/json'}
|
322
|
+
```
|
323
|
+
|
295
324
|
### Response with body specified as IO object
|
296
325
|
|
297
326
|
```ruby
|
@@ -303,6 +332,16 @@ stub_request(:any, "www.example.com").
|
|
303
332
|
Net::HTTP.get('www.example.com', '/') # ===> "abc\n"
|
304
333
|
```
|
305
334
|
|
335
|
+
### Response with JSON body
|
336
|
+
|
337
|
+
```ruby
|
338
|
+
|
339
|
+
stub_request(:any, "www.example.com").
|
340
|
+
to_return_json(body: {foo: "bar"})
|
341
|
+
|
342
|
+
Net::HTTP.get('www.example.com', '/') # ===> "{\"foo\": \"bar\"}"
|
343
|
+
```
|
344
|
+
|
306
345
|
### Response with custom status message
|
307
346
|
|
308
347
|
```ruby
|
@@ -356,7 +395,8 @@ RestClient.post('www.example.net', 'abc') # ===> "abc\n"
|
|
356
395
|
|
357
396
|
### Dynamically evaluated raw responses recorded with `curl -is`
|
358
397
|
|
359
|
-
|
398
|
+
`curl -is www.example.com > /tmp/www.example.com.txt`
|
399
|
+
|
360
400
|
```ruby
|
361
401
|
stub_request(:get, "www.example.com").
|
362
402
|
to_return(lambda { |request| File.new("/tmp/#{request.uri.host.to_s}.txt") })
|
@@ -513,7 +553,7 @@ RestClient.get('www.example.org:8080', '/') # ===> Allowed
|
|
513
553
|
With a `Regexp` matching the URI:
|
514
554
|
|
515
555
|
```ruby
|
516
|
-
WebMock.disable_net_connect!(allow: %r{ample
|
556
|
+
WebMock.disable_net_connect!(allow: %r{ample\.org/foo})
|
517
557
|
|
518
558
|
RestClient.get('www.example.org', '/foo/bar') # ===> Allowed
|
519
559
|
RestClient.get('sample.org', '/foo') # ===> Allowed
|
@@ -523,9 +563,9 @@ RestClient.get('sample.org', '/bar') # ===> Failure
|
|
523
563
|
With an object that responds to `#call`, receiving a `URI` object and returning a boolean:
|
524
564
|
|
525
565
|
```ruby
|
526
|
-
|
566
|
+
denylist = ['google.com', 'facebook.com', 'apple.com']
|
527
567
|
allowed_sites = lambda{|uri|
|
528
|
-
|
568
|
+
denylist.none?{|site| uri.host.include?(site) }
|
529
569
|
}
|
530
570
|
WebMock.disable_net_connect!(allow: allowed_sites)
|
531
571
|
|
@@ -568,7 +608,11 @@ which can be passed to `WebMock.allow_net_connect!` and `WebMock.disable_net_con
|
|
568
608
|
WebMock.allow_net_connect!(net_http_connect_on_start: true)
|
569
609
|
```
|
570
610
|
|
571
|
-
This forces WebMock Net::HTTP adapter to always connect on `Net::HTTP.start`.
|
611
|
+
This forces WebMock Net::HTTP adapter to always connect on `Net::HTTP.start`. At the time of connection being made there is no information about the request or URL yet, therefore WebMock is not able to decide whether to stub a request or not and all connections are allowed. To enable connections only to a specific domain (e.g. your test server) use:
|
612
|
+
|
613
|
+
```ruby
|
614
|
+
WebMock.allow_net_connect!(net_http_connect_on_start: "www.example.com")
|
615
|
+
```
|
572
616
|
|
573
617
|
## Setting Expectations
|
574
618
|
|
@@ -872,6 +916,10 @@ end
|
|
872
916
|
|
873
917
|
Please submit them here [http://github.com/bblimke/webmock/issues](http://github.com/bblimke/webmock/issues)
|
874
918
|
|
919
|
+
## Issue triage [](https://www.codetriage.com/bblimke/webmock)
|
920
|
+
|
921
|
+
You can contribute by triaging issues which may include reproducing bug reports or asking for vital information, such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to webmock on CodeTriage](https://www.codetriage.com/bblimke/webmock).
|
922
|
+
|
875
923
|
## Suggestions
|
876
924
|
|
877
925
|
If you have any suggestions on how to improve WebMock please send an email to the mailing list [groups.google.com/group/webmock-users](http://groups.google.com/group/webmock-users)
|
@@ -1083,13 +1131,89 @@ People who submitted patches and new features or suggested improvements. Many th
|
|
1083
1131
|
* Olle Jonsson
|
1084
1132
|
* Pavel Rosický
|
1085
1133
|
* Geremia Taglialatela
|
1134
|
+
* Koichi Sasada
|
1135
|
+
* Yusuke Endoh
|
1136
|
+
* Grey Baker
|
1137
|
+
* SoonKhen OwYong
|
1138
|
+
* Pavel Valena
|
1139
|
+
* Adam Sokolnicki
|
1140
|
+
* Jeff Felchner
|
1141
|
+
* Eike Send
|
1142
|
+
* Claudio Poli
|
1143
|
+
* Csaba Apagyi
|
1144
|
+
* Frederick Cheung
|
1145
|
+
* Fábio D. Batista
|
1146
|
+
* Andriy Yanko
|
1147
|
+
* y-yagi
|
1148
|
+
* Rafael França
|
1149
|
+
* George Claghorn
|
1150
|
+
* Alex Junger
|
1151
|
+
* Orien Madgwick
|
1152
|
+
* Andrei Sidorov
|
1153
|
+
* Marco Costa
|
1154
|
+
* Ryan Davis
|
1155
|
+
* Brandur
|
1156
|
+
* Samuel Williams
|
1157
|
+
* Patrik Ragnarsson
|
1158
|
+
* Alex Coomans
|
1159
|
+
* Vesa Laakso
|
1160
|
+
* John Hawthorn
|
1161
|
+
* guppy0356
|
1162
|
+
* Thilo Rusche
|
1163
|
+
* Andrew Stuntz
|
1164
|
+
* Lucas Uyezu
|
1165
|
+
* Bruno Sutic
|
1166
|
+
* Ryan Kerr
|
1167
|
+
* Adam Harwood
|
1168
|
+
* Ben Koshy
|
1169
|
+
* Jesse Bowes
|
1170
|
+
* Marek Kasztelnik
|
1171
|
+
* ce07c3
|
1172
|
+
* Jun Jiang
|
1173
|
+
* Oleksiy Kovyrin
|
1174
|
+
* Matt Larraz
|
1175
|
+
* Tony Schneider
|
1176
|
+
* Niklas Hösl
|
1177
|
+
* Johanna Hartmann
|
1178
|
+
* Alex Vondrak
|
1179
|
+
* Will Storey
|
1180
|
+
* Eduardo Hernandez
|
1181
|
+
* ojab
|
1182
|
+
* Giorgio Gambino
|
1183
|
+
* Timmitry
|
1184
|
+
* Michael Fairley
|
1185
|
+
* Ray Zane
|
1186
|
+
* Go Sueyoshi
|
1187
|
+
* Cedric Sohrauer
|
1188
|
+
* Akira Matsuda
|
1189
|
+
* Mark Spangler
|
1190
|
+
* Henrik Nyh
|
1191
|
+
* Yoann Lecuyer
|
1192
|
+
* Lucas Arnaud
|
1193
|
+
* Marc Rohloff
|
1194
|
+
* inkstak
|
1195
|
+
* Yuki Inoue
|
1196
|
+
* Brandon Weaver
|
1197
|
+
* Josh Nichols
|
1198
|
+
* Ricardo Trindade
|
1199
|
+
* Earlopain
|
1200
|
+
* James Brown
|
1201
|
+
* Kazuhiro NISHIYAMA
|
1202
|
+
* Étienne Barrié
|
1203
|
+
* Matt Brown
|
1204
|
+
* Victor Maslov
|
1205
|
+
* Gio Lodi
|
1206
|
+
* Ryan Brooks
|
1207
|
+
* Jacob Frautschi
|
1208
|
+
* Christian Schmidt
|
1209
|
+
* Rodrigo Argumedo
|
1086
1210
|
|
1087
1211
|
For a full list of contributors you can visit the
|
1088
1212
|
[contributors](https://github.com/bblimke/webmock/contributors) page.
|
1089
1213
|
|
1090
1214
|
## Background
|
1091
1215
|
|
1092
|
-
Thank you Fakeweb! This library was inspired by [FakeWeb](
|
1216
|
+
Thank you Fakeweb! This library was inspired by [FakeWeb](https://github.com/chrisk/fakeweb).
|
1093
1217
|
I imported some solutions from that project to WebMock. I also copied some code i.e Net:HTTP adapter.
|
1094
1218
|
Fakeweb architecture unfortunately didn't allow me to extend it easily with the features I needed.
|
1095
1219
|
I also preferred some things to work differently i.e request stub precedence.
|
data/lib/webmock/api.rb
CHANGED
data/lib/webmock/config.rb
CHANGED
data/lib/webmock/cucumber.rb
CHANGED
data/lib/webmock/deprecation.rb
CHANGED
data/lib/webmock/errors.rb
CHANGED
@@ -0,0 +1,228 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'async'
|
5
|
+
require 'async/http'
|
6
|
+
rescue LoadError
|
7
|
+
# async-http not found
|
8
|
+
end
|
9
|
+
|
10
|
+
if defined?(Async::HTTP)
|
11
|
+
module WebMock
|
12
|
+
module HttpLibAdapters
|
13
|
+
class AsyncHttpClientAdapter < HttpLibAdapter
|
14
|
+
adapter_for :async_http_client
|
15
|
+
|
16
|
+
OriginalAsyncHttpClient = Async::HTTP::Client unless const_defined?(:OriginalAsyncHttpClient)
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def enable!
|
20
|
+
Async::HTTP.send(:remove_const, :Client)
|
21
|
+
Async::HTTP.send(:const_set, :Client, Async::HTTP::WebMockClientWrapper)
|
22
|
+
end
|
23
|
+
|
24
|
+
def disable!
|
25
|
+
Async::HTTP.send(:remove_const, :Client)
|
26
|
+
Async::HTTP.send(:const_set, :Client, OriginalAsyncHttpClient)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module Async
|
34
|
+
module HTTP
|
35
|
+
class WebMockClientWrapper < Client
|
36
|
+
def initialize(
|
37
|
+
endpoint,
|
38
|
+
protocol: endpoint.protocol,
|
39
|
+
scheme: endpoint.scheme,
|
40
|
+
authority: endpoint.authority,
|
41
|
+
**options
|
42
|
+
)
|
43
|
+
webmock_endpoint = WebMockEndpoint.new(scheme, authority, protocol)
|
44
|
+
|
45
|
+
@network_client = WebMockClient.new(endpoint, **options)
|
46
|
+
@webmock_client = WebMockClient.new(webmock_endpoint, **options)
|
47
|
+
|
48
|
+
@endpoint = endpoint
|
49
|
+
@scheme = scheme
|
50
|
+
@authority = authority
|
51
|
+
end
|
52
|
+
|
53
|
+
def call(request)
|
54
|
+
request.scheme ||= self.scheme
|
55
|
+
request.authority ||= self.authority
|
56
|
+
|
57
|
+
request_signature = build_request_signature(request)
|
58
|
+
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
59
|
+
webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
|
60
|
+
net_connect_allowed = WebMock.net_connect_allowed?(request_signature.uri)
|
61
|
+
real_request = false
|
62
|
+
|
63
|
+
if webmock_response
|
64
|
+
webmock_response.raise_error_if_any
|
65
|
+
raise Async::TimeoutError, 'WebMock timeout error' if webmock_response.should_timeout
|
66
|
+
WebMockApplication.add_webmock_response(request, webmock_response)
|
67
|
+
response = @webmock_client.call(request)
|
68
|
+
elsif net_connect_allowed
|
69
|
+
response = @network_client.call(request)
|
70
|
+
real_request = true
|
71
|
+
else
|
72
|
+
raise WebMock::NetConnectNotAllowedError.new(request_signature) unless webmock_response
|
73
|
+
end
|
74
|
+
|
75
|
+
if WebMock::CallbackRegistry.any_callbacks?
|
76
|
+
webmock_response ||= build_webmock_response(response)
|
77
|
+
WebMock::CallbackRegistry.invoke_callbacks(
|
78
|
+
{
|
79
|
+
lib: :async_http_client,
|
80
|
+
real_request: real_request
|
81
|
+
},
|
82
|
+
request_signature,
|
83
|
+
webmock_response
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
response
|
88
|
+
end
|
89
|
+
|
90
|
+
def close
|
91
|
+
@network_client.close
|
92
|
+
@webmock_client.close
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def build_request_signature(request)
|
98
|
+
body = request.read
|
99
|
+
request.body = ::Protocol::HTTP::Body::Buffered.wrap(body)
|
100
|
+
WebMock::RequestSignature.new(
|
101
|
+
request.method.downcase.to_sym,
|
102
|
+
"#{request.scheme}://#{request.authority}#{request.path}",
|
103
|
+
headers: request.headers.to_h,
|
104
|
+
body: body
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
def build_webmock_response(response)
|
109
|
+
body = response.read
|
110
|
+
response.body = ::Protocol::HTTP::Body::Buffered.wrap(body)
|
111
|
+
|
112
|
+
webmock_response = WebMock::Response.new
|
113
|
+
webmock_response.status = [
|
114
|
+
response.status,
|
115
|
+
::Protocol::HTTP1::Reason::DESCRIPTIONS[response.status]
|
116
|
+
]
|
117
|
+
webmock_response.headers = build_webmock_response_headers(response)
|
118
|
+
webmock_response.body = body
|
119
|
+
webmock_response
|
120
|
+
end
|
121
|
+
|
122
|
+
def build_webmock_response_headers(response)
|
123
|
+
response.headers.each.each_with_object({}) do |(k, v), o|
|
124
|
+
o[k] ||= []
|
125
|
+
o[k] << v
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
class WebMockClient < Client
|
131
|
+
end
|
132
|
+
|
133
|
+
class WebMockEndpoint
|
134
|
+
def initialize(scheme, authority, protocol)
|
135
|
+
@scheme = scheme
|
136
|
+
@authority = authority
|
137
|
+
@protocol = protocol
|
138
|
+
end
|
139
|
+
|
140
|
+
attr :scheme, :authority, :protocol
|
141
|
+
|
142
|
+
def connect
|
143
|
+
server_socket, client_socket = create_connected_sockets
|
144
|
+
Async(transient: true) do
|
145
|
+
accept_socket(server_socket)
|
146
|
+
end
|
147
|
+
client_socket
|
148
|
+
end
|
149
|
+
|
150
|
+
def inspect
|
151
|
+
"\#<#{self.class}> #{scheme}://#{authority} protocol=#{protocol}"
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
def socket_class
|
157
|
+
defined?(Async::IO::Socket) ? Async::IO::Socket : Socket
|
158
|
+
end
|
159
|
+
|
160
|
+
def create_connected_sockets
|
161
|
+
pair = begin
|
162
|
+
socket_class.pair(Socket::AF_UNIX, Socket::SOCK_STREAM)
|
163
|
+
rescue Errno::EAFNOSUPPORT
|
164
|
+
socket_class.pair(Socket::AF_INET, Socket::SOCK_STREAM)
|
165
|
+
end
|
166
|
+
pair.tap do |sockets|
|
167
|
+
sockets.each do |socket|
|
168
|
+
socket.instance_variable_set :@alpn_protocol, nil
|
169
|
+
socket.instance_eval do
|
170
|
+
def alpn_protocol
|
171
|
+
nil # means HTTP11 will be used for HTTPS
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def accept_socket(socket)
|
179
|
+
server = Async::HTTP::Server.new(WebMockApplication, self)
|
180
|
+
server.accept(socket, socket.remote_address)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
module WebMockApplication
|
185
|
+
WEBMOCK_REQUEST_ID_HEADER = 'x-webmock-request-id'.freeze
|
186
|
+
|
187
|
+
class << self
|
188
|
+
def call(request)
|
189
|
+
request.read
|
190
|
+
webmock_response = get_webmock_response(request)
|
191
|
+
build_response(webmock_response)
|
192
|
+
end
|
193
|
+
|
194
|
+
def add_webmock_response(request, webmock_response)
|
195
|
+
webmock_request_id = request.object_id.to_s
|
196
|
+
request.headers.add(WEBMOCK_REQUEST_ID_HEADER, webmock_request_id)
|
197
|
+
webmock_responses[webmock_request_id] = webmock_response
|
198
|
+
end
|
199
|
+
|
200
|
+
def get_webmock_response(request)
|
201
|
+
webmock_request_id = request.headers[WEBMOCK_REQUEST_ID_HEADER][0]
|
202
|
+
webmock_responses.fetch(webmock_request_id)
|
203
|
+
end
|
204
|
+
|
205
|
+
private
|
206
|
+
|
207
|
+
def webmock_responses
|
208
|
+
@webmock_responses ||= {}
|
209
|
+
end
|
210
|
+
|
211
|
+
def build_response(webmock_response)
|
212
|
+
headers = (webmock_response.headers || {}).each_with_object([]) do |(k, value), o|
|
213
|
+
Array(value).each do |v|
|
214
|
+
o.push [k, v]
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
::Protocol::HTTP::Response[
|
219
|
+
webmock_response.status[0],
|
220
|
+
headers,
|
221
|
+
webmock_response.body
|
222
|
+
]
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'curb'
|
3
5
|
rescue LoadError
|
@@ -5,7 +7,7 @@ rescue LoadError
|
|
5
7
|
end
|
6
8
|
|
7
9
|
if defined?(Curl)
|
8
|
-
WebMock::VersionChecker.new('Curb', Curl::CURB_VERSION, '0.7.16', '0.
|
10
|
+
WebMock::VersionChecker.new('Curb', Curl::CURB_VERSION, '0.7.16', '1.0.1', ['0.8.7']).check_version!
|
9
11
|
|
10
12
|
module WebMock
|
11
13
|
module HttpLibAdapters
|
@@ -54,7 +56,6 @@ if defined?(Curl)
|
|
54
56
|
|
55
57
|
module Curl
|
56
58
|
class WebMockCurlEasy < Curl::Easy
|
57
|
-
|
58
59
|
def curb_or_webmock
|
59
60
|
request_signature = build_request_signature
|
60
61
|
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
@@ -129,7 +130,7 @@ if defined?(Curl)
|
|
129
130
|
def headers_as_hash(headers)
|
130
131
|
if headers.is_a?(Array)
|
131
132
|
headers.inject({}) {|hash, header|
|
132
|
-
name, value = header.split(":").map(&:strip)
|
133
|
+
name, value = header.split(":", 2).map(&:strip)
|
133
134
|
hash[name] = value
|
134
135
|
hash
|
135
136
|
}
|
@@ -271,6 +272,8 @@ if defined?(Curl)
|
|
271
272
|
def perform
|
272
273
|
@webmock_method ||= :get
|
273
274
|
curb_or_webmock { super }
|
275
|
+
ensure
|
276
|
+
reset_webmock_method
|
274
277
|
end
|
275
278
|
|
276
279
|
def put_data= data
|
@@ -333,8 +336,16 @@ if defined?(Curl)
|
|
333
336
|
METHOD
|
334
337
|
end
|
335
338
|
|
339
|
+
def reset_webmock_method
|
340
|
+
@webmock_method = :get
|
341
|
+
end
|
342
|
+
|
336
343
|
def reset
|
337
344
|
instance_variable_set(:@body_str, nil)
|
345
|
+
instance_variable_set(:@content_type, nil)
|
346
|
+
instance_variable_set(:@header_str, nil)
|
347
|
+
instance_variable_set(:@last_effective_url, nil)
|
348
|
+
instance_variable_set(:@response_code, nil)
|
338
349
|
super
|
339
350
|
end
|
340
351
|
end
|