webmock 3.33.0 → 3.34.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 41c4be4a917d40c0448cdf920de152862f1ce887e379e49121020d506757c16d
4
- data.tar.gz: 71ed3dc5e3df9671c7ce188fa579b86379ab365f95b666c7eeee7bf6851dc836
3
+ metadata.gz: b66b694440da9739d8d23ccd8a260260739199235f076f4854387f7029c0c976
4
+ data.tar.gz: 96abe5bbe31e475bcec618aff66d43ac724b7cf15b08883ae864d62cac826e7c
5
5
  SHA512:
6
- metadata.gz: 79843a07ef28cee5968bf6e3eb4b5eac10f688c3aba9caeb44cd30c74ec28ee8e0129eef69eab8d1a87e3991512b63c96589bbf52aaa912f12217ed86b20b4d2
7
- data.tar.gz: '009710347fc3bf01b14ab050ba19c316af32a8a2803b0d40b3388be7ed824a5e6de371a860810df8ebff0de2dd588ad6071c876cf79a029835ccab32c8d48fe4'
6
+ metadata.gz: 99395c27d7c6c270f37309e69da7f3688c43b8f158327d23b62b9829b3fff7a667280542017c71f18e2b822de6639394b2aeaa078aae7b7c67d7fd497363e918
7
+ data.tar.gz: 9378a048d2a03b1309eff3b5264ddca35e4f9268399a92e98147fa0e2d60e376d31ca2f1ccaca912f6d7ca859268b1d9ce173530e885c5055b99f3c2632bfd46
data/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # Changelog
2
2
 
3
+ # 3.34.0
4
+
5
+ * Allow `with(query: :any)` to match any query string (#1099)
6
+
7
+ `stub_request(:get, "www.example.com").with(query: :any)` matches requests with any query string, or none. RSpec's `anything` works the same way. Previously, this raised `NoMethodError`, and you had to write `with(query: hash_including({}))`.
8
+
9
+ Use a URL without query parameters when passing `query: :any`. Otherwise, WebMock raises `ArgumentError`.
10
+
11
+ Thanks to [nightpool](https://github.com/nightpool)
12
+
13
+ * Raise a clear `ArgumentError` for an unsupported `query` option
14
+
15
+ Previously, a value such as `with(query: :all)` raised `NoMethodError` (undefined method `split`). The new error lists the supported values.
16
+
17
+ * Show `anything` for keys given without a value to `hash_including` or `hash_excluding` outside RSpec
18
+
19
+ Previously, with Minitest or Test::Unit, messages showed `#<WebMock::Matchers::AnyArgMatcher:0x...>`, for example for `with(query: hash_including(:a))`. RSpec's own matchers already showed `anything`.
20
+
21
+ * Provide `HTTP_HOST` to `to_rack` apps when the client has not supplied a Host header (#1084)
22
+
23
+ Previously, requests from some HTTP clients reached the Rack app without `HTTP_HOST`. This caused host checks such as Sinatra's `HostAuthorization` to see an empty host.
24
+
25
+ WebMock now fills in the host from the request URL, including the port when it is not the default. An explicit Host header is preserved.
26
+
27
+ Thanks to [Benoit Tigeot](https://github.com/benoittgt)
28
+
29
+ * Fix Rack compatibility for `to_rack` apps
30
+
31
+ The request environment now passes `Rack::Lint`.
32
+
33
+ `SERVER_PORT` and `CONTENT_LENGTH` are now strings. If your app or tests read them directly, use string comparisons, such as `env['SERVER_PORT'] == "80"`. The environment also includes `SERVER_PROTOCOL`.
34
+
35
+ `CONTENT_TYPE` is omitted when the request has no content type. The `Content-Length` header is passed only as `CONTENT_LENGTH`, without an extra `HTTP_CONTENT_LENGTH` entry. `Transfer-Encoding` is removed because the body has already been decoded.
36
+
37
+ Repeated header values are joined into one string. Header values and the body read from `rack.input` now use binary (`ASCII-8BIT`) strings.
38
+
3
39
  # 3.33.0
4
40
 
5
41
  * Return `effective_url` as a String for stubbed Typhoeus responses (#869)
data/README.md CHANGED
@@ -299,6 +299,15 @@ Net::HTTP.get('www.example.com',
299
299
  '/thing/5.json?x=1&y=2&z=3&anyParam=4') # ===> Success
300
300
  ```
301
301
 
302
+ ### Matching any query params
303
+
304
+ ```ruby
305
+ stub_request(:get, "www.example.com").with(query: :any)
306
+
307
+ RestClient.get("http://www.example.com/?q=example") # ===> Success
308
+ RestClient.get("http://www.example.com/") # ===> Success
309
+ ```
310
+
302
311
  ### Matching query params using hash
303
312
 
304
313
  ```ruby
@@ -10,6 +10,10 @@ module WebMock
10
10
  def ==(other)
11
11
  true
12
12
  end
13
+
14
+ def inspect
15
+ "anything"
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -27,37 +27,56 @@ module WebMock
27
27
 
28
28
  def build_rack_env(request)
29
29
  uri = request.uri
30
+ port = uri.inferred_port
30
31
  headers = (request.headers || {}).dup
31
- body = request.body || ''
32
+ body = (request.body || '').b
33
+ content_type = headers.delete('Content-Type')
34
+ headers.delete('Content-Length')
35
+ # The body is already decoded, as a server passes it on.
36
+ headers.delete('Transfer-Encoding')
32
37
 
33
38
  env = {
34
39
  # CGI variables specified by Rack
35
- 'REQUEST_METHOD' => request.method.to_s.upcase,
36
- 'CONTENT_TYPE' => headers.delete('Content-Type'),
37
- 'CONTENT_LENGTH' => body.bytesize,
38
- 'PATH_INFO' => uri.path,
39
- 'QUERY_STRING' => uri.query || '',
40
- 'SERVER_NAME' => uri.host,
41
- 'SERVER_PORT' => uri.port,
42
- 'SCRIPT_NAME' => ""
40
+ 'REQUEST_METHOD' => request.method.to_s.upcase,
41
+ 'CONTENT_LENGTH' => body.bytesize.to_s,
42
+ 'PATH_INFO' => uri.path,
43
+ 'QUERY_STRING' => uri.query || '',
44
+ 'SERVER_NAME' => uri.host,
45
+ 'SERVER_PORT' => port.to_s,
46
+ 'SERVER_PROTOCOL' => 'HTTP/1.1',
47
+ 'SCRIPT_NAME' => ""
43
48
  }
49
+ env['CONTENT_TYPE'] = header_value('Content-Type', content_type) if content_type
44
50
 
45
51
  env['HTTP_AUTHORIZATION'] = 'Basic ' + [uri.userinfo].pack('m').delete("\r\n") if uri.userinfo
46
52
 
47
53
  # Rack-specific variables
48
54
  env['rack.input'] = StringIO.new(body)
49
55
  env['rack.errors'] = $stderr
50
- if !Rack.const_defined?(:RELEASE) || Rack::RELEASE < "3"
51
- env['rack.version'] = Rack::VERSION
56
+ if !Rack.const_defined?(:RELEASE) || Gem::Version.new(Rack::RELEASE) < Gem::Version.new("3")
57
+ env['rack.version'] = Rack::VERSION
58
+ env['rack.multithread'] = false
59
+ env['rack.multiprocess'] = false
52
60
  end
53
61
  env['rack.url_scheme'] = uri.scheme
54
62
  env['rack.run_once'] = true
55
63
 
56
64
  headers.each do |k, v|
57
- env["HTTP_#{k.tr('-','_').upcase}"] = v
65
+ env["HTTP_#{k.tr('-','_').upcase}"] = header_value(k, v)
58
66
  end
59
67
 
68
+ # Many clients add Host only when sending, so fill it in as they would.
69
+ env['HTTP_HOST'] ||= port == uri.default_port ? uri.host : "#{uri.host}:#{port}"
70
+
60
71
  env
61
72
  end
73
+
74
+ private
75
+
76
+ # Like a server, pass header values as bytes and join repeated ones. Rack
77
+ # splits cookies on "; ", so join those that way.
78
+ def header_value(name, value)
79
+ Array(value).map { |v| v.to_s.b }.join(name == 'Cookie' ? '; ' : WebMock::Util::Headers::JOIN)
80
+ end
62
81
  end
63
82
  end
@@ -10,6 +10,10 @@ module WebMock
10
10
  def rSpecHashExcludingMatcher?(matcher)
11
11
  matcher.class.name =~ /R?Spec::Mocks::ArgumentMatchers::HashExcludingMatcher/
12
12
  end
13
+
14
+ def rSpecAnyArgMatcher?(matcher)
15
+ matcher.class.name =~ /R?Spec::Mocks::ArgumentMatchers::AnyArgMatcher/
16
+ end
13
17
  end
14
18
 
15
19
  class RequestPattern
@@ -129,6 +133,10 @@ module WebMock
129
133
  def add_query_params(query_params)
130
134
  @query_params = if query_params.is_a?(Hash)
131
135
  query_params
136
+ elsif query_params.equal?(:any) \
137
+ || query_params.is_a?(WebMock::Matchers::AnyArgMatcher) \
138
+ || rSpecAnyArgMatcher?(query_params)
139
+ WebMock::Matchers::AnyArgMatcher.new(nil)
132
140
  elsif query_params.is_a?(WebMock::Matchers::HashIncludingMatcher) \
133
141
  || query_params.is_a?(WebMock::Matchers::HashExcludingMatcher)
134
142
  query_params
@@ -136,8 +144,10 @@ module WebMock
136
144
  WebMock::Matchers::HashIncludingMatcher.from_rspec_matcher(query_params)
137
145
  elsif rSpecHashExcludingMatcher?(query_params)
138
146
  WebMock::Matchers::HashExcludingMatcher.from_rspec_matcher(query_params)
139
- else
147
+ elsif query_params.nil? || query_params.is_a?(String)
140
148
  WebMock::Util::QueryMapper.query_to_values(query_params, notation: Config.instance.query_values_notation)
149
+ else
150
+ raise ArgumentError, "Query should be a String, Hash, :any, nil, or a hash_including or hash_excluding matcher. Got: #{query_params.class}"
141
151
  end
142
152
  end
143
153
 
@@ -153,6 +163,10 @@ module WebMock
153
163
 
154
164
  private
155
165
 
166
+ def raise_any_query_with_uri_query
167
+ raise ArgumentError, "query: :any can't be combined with a query in the URI #{pattern_inspect}, because no request would match. Remove the query from the URI."
168
+ end
169
+
156
170
  def pattern_inspect
157
171
  @pattern.inspect
158
172
  end
@@ -180,12 +194,17 @@ module WebMock
180
194
 
181
195
  class URIAddressablePattern < URIPattern
182
196
  def add_query_params(query_params)
197
+ super(query_params)
198
+ # With query params, the template is matched against the URI without its
199
+ # query, so a literal query in the template can never match.
200
+ if @query_params.is_a?(WebMock::Matchers::AnyArgMatcher) && @pattern.pattern.gsub(/\{[^}]*\}/, '').include?('?')
201
+ raise_any_query_with_uri_query
202
+ end
183
203
  @@add_query_params_warned ||= false
184
204
  if not @@add_query_params_warned
185
205
  @@add_query_params_warned = true
186
206
  warn "WebMock warning: ignoring query params in RFC 6570 template and checking them with WebMock"
187
207
  end
188
- super(query_params)
189
208
  end
190
209
 
191
210
  private
@@ -230,6 +249,9 @@ module WebMock
230
249
  query_hash = (WebMock::Util::QueryMapper.query_to_values(@pattern.query, notation: Config.instance.query_values_notation) || {}).merge(@query_params)
231
250
  @pattern.query = WebMock::Util::QueryMapper.values_to_query(query_hash, notation: WebMock::Config.instance.query_values_notation)
232
251
  @query_params = nil
252
+ elsif @query_params.is_a?(WebMock::Matchers::AnyArgMatcher) && @pattern.query
253
+ # The URI is then compared without its query, so it could never match.
254
+ raise_any_query_with_uri_query
233
255
  end
234
256
  end
235
257
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebMock
4
- VERSION = '3.33.0' unless defined?(::WebMock::VERSION)
4
+ VERSION = '3.34.0' unless defined?(::WebMock::VERSION)
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webmock
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.33.0
4
+ version: 3.34.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bartosz Blimke
@@ -360,9 +360,9 @@ licenses:
360
360
  - MIT
361
361
  metadata:
362
362
  bug_tracker_uri: https://github.com/bblimke/webmock/issues
363
- changelog_uri: https://github.com/bblimke/webmock/blob/v3.33.0/CHANGELOG.md
364
- documentation_uri: https://www.rubydoc.info/gems/webmock/3.33.0
365
- source_code_uri: https://github.com/bblimke/webmock/tree/v3.33.0
363
+ changelog_uri: https://github.com/bblimke/webmock/blob/v3.34.0/CHANGELOG.md
364
+ documentation_uri: https://www.rubydoc.info/gems/webmock/3.34.0
365
+ source_code_uri: https://github.com/bblimke/webmock/tree/v3.34.0
366
366
  wiki_uri: https://github.com/bblimke/webmock/wiki
367
367
  rdoc_options: []
368
368
  require_paths: