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.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +476 -2
  3. data/README.md +166 -42
  4. data/lib/webmock/api.rb +2 -0
  5. data/lib/webmock/assertion_failure.rb +2 -0
  6. data/lib/webmock/callback_registry.rb +2 -0
  7. data/lib/webmock/config.rb +2 -0
  8. data/lib/webmock/cucumber.rb +2 -0
  9. data/lib/webmock/deprecation.rb +2 -0
  10. data/lib/webmock/errors.rb +2 -0
  11. data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +228 -0
  12. data/lib/webmock/http_lib_adapters/curb_adapter.rb +14 -3
  13. data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +22 -9
  14. data/lib/webmock/http_lib_adapters/excon_adapter.rb +5 -0
  15. data/lib/webmock/http_lib_adapters/http_lib_adapter.rb +2 -0
  16. data/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +2 -0
  17. data/lib/webmock/http_lib_adapters/http_rb/client.rb +4 -1
  18. data/lib/webmock/http_lib_adapters/http_rb/request.rb +17 -5
  19. data/lib/webmock/http_lib_adapters/http_rb/response.rb +49 -5
  20. data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +11 -3
  21. data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +8 -2
  22. data/lib/webmock/http_lib_adapters/http_rb_adapter.rb +7 -5
  23. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +25 -7
  24. data/lib/webmock/http_lib_adapters/manticore_adapter.rb +35 -15
  25. data/lib/webmock/http_lib_adapters/net_http.rb +59 -112
  26. data/lib/webmock/http_lib_adapters/net_http_response.rb +3 -1
  27. data/lib/webmock/http_lib_adapters/patron_adapter.rb +4 -2
  28. data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +18 -2
  29. data/lib/webmock/matchers/any_arg_matcher.rb +2 -0
  30. data/lib/webmock/matchers/hash_argument_matcher.rb +2 -0
  31. data/lib/webmock/matchers/hash_excluding_matcher.rb +2 -0
  32. data/lib/webmock/matchers/hash_including_matcher.rb +2 -0
  33. data/lib/webmock/minitest.rb +2 -0
  34. data/lib/webmock/rack_response.rb +5 -1
  35. data/lib/webmock/request_body_diff.rb +3 -1
  36. data/lib/webmock/request_execution_verifier.rb +2 -0
  37. data/lib/webmock/request_pattern.rb +118 -61
  38. data/lib/webmock/request_registry.rb +2 -0
  39. data/lib/webmock/request_signature.rb +4 -2
  40. data/lib/webmock/request_signature_snippet.rb +2 -0
  41. data/lib/webmock/request_stub.rb +34 -0
  42. data/lib/webmock/response.rb +22 -14
  43. data/lib/webmock/responses_sequence.rb +2 -0
  44. data/lib/webmock/rspec/matchers/request_pattern_matcher.rb +2 -0
  45. data/lib/webmock/rspec/matchers/webmock_matcher.rb +2 -0
  46. data/lib/webmock/rspec/matchers.rb +2 -0
  47. data/lib/webmock/rspec.rb +4 -1
  48. data/lib/webmock/stub_registry.rb +28 -11
  49. data/lib/webmock/stub_request_snippet.rb +2 -0
  50. data/lib/webmock/test_unit.rb +3 -3
  51. data/lib/webmock/util/hash_counter.rb +12 -6
  52. data/lib/webmock/util/hash_keys_stringifier.rb +2 -0
  53. data/lib/webmock/util/hash_validator.rb +2 -0
  54. data/lib/webmock/util/headers.rb +23 -10
  55. data/lib/webmock/util/parsers/json.rb +72 -0
  56. data/lib/webmock/util/parsers/parse_error.rb +7 -0
  57. data/lib/webmock/util/parsers/xml.rb +16 -0
  58. data/lib/webmock/util/query_mapper.rb +6 -2
  59. data/lib/webmock/util/uri.rb +11 -9
  60. data/lib/webmock/util/values_stringifier.rb +2 -0
  61. data/lib/webmock/util/version_checker.rb +7 -5
  62. data/lib/webmock/version.rb +3 -1
  63. data/lib/webmock/webmock.rb +22 -3
  64. data/lib/webmock.rb +5 -2
  65. metadata +99 -175
  66. data/.gemtest +0 -0
  67. data/.gitignore +0 -34
  68. data/.rspec-tm +0 -2
  69. data/.travis.yml +0 -21
  70. data/Gemfile +0 -9
  71. data/Rakefile +0 -30
  72. data/lib/webmock/util/json.rb +0 -67
  73. data/minitest/test_helper.rb +0 -34
  74. data/minitest/test_webmock.rb +0 -9
  75. data/minitest/webmock_spec.rb +0 -60
  76. data/spec/acceptance/curb/curb_spec.rb +0 -481
  77. data/spec/acceptance/curb/curb_spec_helper.rb +0 -147
  78. data/spec/acceptance/em_http_request/em_http_request_spec.rb +0 -406
  79. data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +0 -77
  80. data/spec/acceptance/excon/excon_spec.rb +0 -77
  81. data/spec/acceptance/excon/excon_spec_helper.rb +0 -50
  82. data/spec/acceptance/http_rb/http_rb_spec.rb +0 -82
  83. data/spec/acceptance/http_rb/http_rb_spec_helper.rb +0 -54
  84. data/spec/acceptance/httpclient/httpclient_spec.rb +0 -217
  85. data/spec/acceptance/httpclient/httpclient_spec_helper.rb +0 -57
  86. data/spec/acceptance/manticore/manticore_spec.rb +0 -56
  87. data/spec/acceptance/manticore/manticore_spec_helper.rb +0 -35
  88. data/spec/acceptance/net_http/net_http_shared.rb +0 -153
  89. data/spec/acceptance/net_http/net_http_spec.rb +0 -331
  90. data/spec/acceptance/net_http/net_http_spec_helper.rb +0 -64
  91. data/spec/acceptance/net_http/real_net_http_spec.rb +0 -20
  92. data/spec/acceptance/patron/patron_spec.rb +0 -125
  93. data/spec/acceptance/patron/patron_spec_helper.rb +0 -54
  94. data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +0 -313
  95. data/spec/acceptance/shared/callbacks.rb +0 -147
  96. data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +0 -36
  97. data/spec/acceptance/shared/enabling_and_disabling_webmock.rb +0 -95
  98. data/spec/acceptance/shared/precedence_of_stubs.rb +0 -15
  99. data/spec/acceptance/shared/request_expectations.rb +0 -923
  100. data/spec/acceptance/shared/returning_declared_responses.rb +0 -388
  101. data/spec/acceptance/shared/stubbing_requests.rb +0 -638
  102. data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +0 -135
  103. data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +0 -60
  104. data/spec/acceptance/webmock_shared.rb +0 -41
  105. data/spec/fixtures/test.txt +0 -1
  106. data/spec/quality_spec.rb +0 -84
  107. data/spec/spec_helper.rb +0 -48
  108. data/spec/support/example_curl_output.txt +0 -22
  109. data/spec/support/failures.rb +0 -9
  110. data/spec/support/my_rack_app.rb +0 -53
  111. data/spec/support/network_connection.rb +0 -19
  112. data/spec/support/webmock_server.rb +0 -69
  113. data/spec/unit/api_spec.rb +0 -175
  114. data/spec/unit/errors_spec.rb +0 -129
  115. data/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +0 -17
  116. data/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +0 -12
  117. data/spec/unit/matchers/hash_excluding_matcher_spec.rb +0 -61
  118. data/spec/unit/matchers/hash_including_matcher_spec.rb +0 -87
  119. data/spec/unit/rack_response_spec.rb +0 -112
  120. data/spec/unit/request_body_diff_spec.rb +0 -90
  121. data/spec/unit/request_execution_verifier_spec.rb +0 -208
  122. data/spec/unit/request_pattern_spec.rb +0 -596
  123. data/spec/unit/request_registry_spec.rb +0 -95
  124. data/spec/unit/request_signature_snippet_spec.rb +0 -89
  125. data/spec/unit/request_signature_spec.rb +0 -155
  126. data/spec/unit/request_stub_spec.rb +0 -199
  127. data/spec/unit/response_spec.rb +0 -282
  128. data/spec/unit/stub_registry_spec.rb +0 -103
  129. data/spec/unit/stub_request_snippet_spec.rb +0 -115
  130. data/spec/unit/util/hash_counter_spec.rb +0 -39
  131. data/spec/unit/util/hash_keys_stringifier_spec.rb +0 -27
  132. data/spec/unit/util/headers_spec.rb +0 -28
  133. data/spec/unit/util/json_spec.rb +0 -33
  134. data/spec/unit/util/query_mapper_spec.rb +0 -150
  135. data/spec/unit/util/uri_spec.rb +0 -299
  136. data/spec/unit/util/version_checker_spec.rb +0 -65
  137. data/spec/unit/webmock_spec.rb +0 -11
  138. data/test/http_request.rb +0 -24
  139. data/test/shared_test.rb +0 -108
  140. data/test/test_helper.rb +0 -23
  141. data/test/test_webmock.rb +0 -6
  142. data/webmock.gemspec +0 -46
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  WebMock
2
2
  =======
3
- [![Gem Version](https://badge.fury.io/rb/webmock.svg)](http://badge.fury.io/rb/webmock) [![Build Status](https://secure.travis-ci.org/bblimke/webmock.svg?branch=master)](http://travis-ci.org/bblimke/webmock) [![Dependency Status](https://gemnasium.com/bblimke/webmock.svg)](http://gemnasium.com/bblimke/webmock) [![Code Climate](https://codeclimate.com/github/bblimke/webmock/badges/gpa.svg)](https://codeclimate.com/github/bblimke/webmock) [![Mentioned in Awesome Ruby](https://awesome.re/mentioned-badge.svg)](https://github.com/markets/awesome-ruby) [![Inline docs](http://inch-ci.org/github/bblimke/webmock.svg?branch=master)](http://inch-ci.org/github/bblimke/webmock)
3
+ [![Gem Version](https://badge.fury.io/rb/webmock.svg)](http://badge.fury.io/rb/webmock)
4
+ [![Build Status](https://github.com/bblimke/webmock/actions/workflows/CI.yml/badge.svg?branch=master)](https://github.com/bblimke/webmock/actions)
5
+ [![Code Climate](https://codeclimate.com/github/bblimke/webmock/badges/gpa.svg)](https://codeclimate.com/github/bblimke/webmock)
6
+ [![Mentioned in Awesome Ruby](https://awesome.re/mentioned-badge.svg)](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
- * Net::HTTP and libraries based on Net::HTTP (i.e RightHttpConnection, REST Client, HTTParty)
23
- * HTTPClient
24
- * Patron
25
- * EM-HTTP-Request
26
- * Curb (currently only Curb::Easy)
27
- * Typhoeus (currently only Typhoeus::Hydra)
28
- * Excon
29
- * HTTP Gem
30
- * Manticore
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.2
36
- * MRI 2.3
37
- * MRI 2.4
38
- * MRI 2.5
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
- gem install webmock
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
- git clone http://github.com/bblimke/webmock.git
49
- cd webmock
50
- rake install
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
- ### Test::Unit
76
+ ### Cucumber
57
77
 
58
- Add the following code to `test/test_helper.rb`
78
+ Create a file `features/support/webmock.rb` with the following contents:
59
79
 
60
80
  ```ruby
61
- require 'webmock/test_unit'
81
+ require 'webmock/cucumber'
62
82
  ```
63
83
 
64
- ### RSpec
84
+ ### MiniTest
65
85
 
66
- Add the following code to `spec/spec_helper`:
86
+ Add the following code to `test/test_helper`:
67
87
 
68
88
  ```ruby
69
- require 'webmock/rspec'
89
+ require 'webmock/minitest'
70
90
  ```
71
91
 
72
- ### MiniTest
92
+ ### RSpec
73
93
 
74
- Add the following code to `test/test_helper`:
94
+ Add the following code to `spec/spec_helper`:
75
95
 
76
96
  ```ruby
77
- require 'webmock/minitest'
97
+ require 'webmock/rspec'
78
98
  ```
79
99
 
80
- ### Cucumber
100
+ ### Test::Unit
81
101
 
82
- Create a file `features/support/webmock.rb` with the following contents:
102
+ Add the following code to `test/test_helper.rb`
83
103
 
84
104
  ```ruby
85
- require 'webmock/cucumber'
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
- ## Examples
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
- `curl -is www.example.com > /tmp/www.example.com.txt`
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.org/foo})
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
- blacklist = ['google.com', 'facebook.com', 'apple.com']
566
+ denylist = ['google.com', 'facebook.com', 'apple.com']
527
567
  allowed_sites = lambda{|uri|
528
- blacklist.none?{|site| uri.host.include?(site) }
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 [![Open Source Helpers](https://www.codetriage.com/bblimke/webmock/badges/users.svg)](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](http://fakeweb.rubyforge.org).
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  module API
3
5
  extend self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class AssertionFailure
3
5
  @error_class = RuntimeError
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class CallbackRegistry
3
5
  @@callbacks = []
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class Config
3
5
  include Singleton
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'webmock'
2
4
  require 'webmock/rspec/matchers'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class Deprecation
3
5
  class << self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
 
3
5
  class NetConnectNotAllowedError < Exception
@@ -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.9.1', ['0.8.7']).check_version!
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