rack-test 2.0.2 → 2.2.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/History.md +40 -0
- data/README.md +1 -1
- data/lib/rack/test/cookie_jar.rb +18 -13
- data/lib/rack/test/methods.rb +5 -6
- data/lib/rack/test/uploaded_file.rb +11 -21
- data/lib/rack/test/version.rb +1 -1
- data/lib/rack/test.rb +22 -54
- metadata +6 -8
- data/lib/rack/mock_session.rb +0 -2
- data/lib/rack/test/mock_digest_request.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c648ce9c6c053f9168116fa0ff70ac3ce4d6944326cca519fc2f7f1bb3c4f1d
|
4
|
+
data.tar.gz: 8c8d8c7b5c41facc400a1f95533af2e94c7c6eb42ed55ba92b5e38689134e3d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5414edd21a3f105513f6068d799fd25fd61672dcd50d0eedbb04b8e05e5224f62f9fcd5014456c99b17ae02c86e38e16077cce27b2c04bcc285214bb49213d45
|
7
|
+
data.tar.gz: 5f21ac1f5f8ee2f82d6c3ce65e0cb88ed66e055178c120b935be24a838ee1fc126d1a6070ea4833626e314d631c052748eccdce66db801bfafda01d7bc9c2b42
|
data/History.md
CHANGED
@@ -1,3 +1,43 @@
|
|
1
|
+
## 2.2.0 / 2024-12-23
|
2
|
+
|
3
|
+
* Bug fixes:
|
4
|
+
* `Rack::Test::Cookie` now parses cookie parameters using a
|
5
|
+
case-insensitive approach (Guillaume Malette #349)
|
6
|
+
|
7
|
+
* Minor enhancements:
|
8
|
+
* Arrays of cookies containing a blank cookie are now handled
|
9
|
+
correctly when processing responses. (Martin Emde #343)
|
10
|
+
* `Rack::Test::UploadedFile` no longer uses a finalizer for named
|
11
|
+
paths to close and unlink the created Tempfile. Tempfile itself
|
12
|
+
uses a finalizer to close and unlink itself, so there is no
|
13
|
+
reason for `Rack::Test::UploadedFile` to do so (Jeremy Evans #338)
|
14
|
+
|
15
|
+
## 2.1.0 / 2023-03-14
|
16
|
+
|
17
|
+
* Breaking changes:
|
18
|
+
* Digest authentication support, deprecated in 2.0.0, has been
|
19
|
+
removed (Jeremy Evans #307)
|
20
|
+
* requiring rack/mock_session, deprecated in 2.0.0, has been removed
|
21
|
+
(Jeremy Evans #307)
|
22
|
+
|
23
|
+
* Minor enhancements:
|
24
|
+
* The `original_filename` for `Rack::Test::UploadedFile` can now be
|
25
|
+
set even if the content of the file comes from a file path
|
26
|
+
(Stuart Chinery #314)
|
27
|
+
* Add `Rack::Test::Session#restore_state`, for executing a block
|
28
|
+
and restoring current state (last request, last response, and
|
29
|
+
cookies) after the block (Jeremy Evans #316)
|
30
|
+
* Make `Rack::Test::Methods` support `default_host` method similar to
|
31
|
+
`app`, which will set the default host used for requests to the app
|
32
|
+
(Jeremy Evans #317 #318)
|
33
|
+
* Allow responses to set cookie paths not matching the current
|
34
|
+
request URI. Such cookies will only be sent for paths matching
|
35
|
+
the cookie path (Chris Waters #322)
|
36
|
+
* Ignore leading dot for cookie domains, per RFC 6265 (Stephen Crosby
|
37
|
+
#329)
|
38
|
+
* Avoid creating empty multipart body if params is empty in
|
39
|
+
`Rack::Test::Session#env_for` (Ryunosuke Sato #331)
|
40
|
+
|
1
41
|
## 2.0.2 / 2022-06-28
|
2
42
|
|
3
43
|
* Bug fixes:
|
data/README.md
CHANGED
data/lib/rack/test/cookie_jar.rb
CHANGED
@@ -12,7 +12,7 @@ module Rack
|
|
12
12
|
|
13
13
|
# The name of the cookie, will be a string
|
14
14
|
attr_reader :name
|
15
|
-
|
15
|
+
|
16
16
|
# The value of the cookie, will be a string or nil if there is no value.
|
17
17
|
attr_reader :value
|
18
18
|
|
@@ -28,10 +28,11 @@ module Rack
|
|
28
28
|
@raw, options = raw.split(/[;,] */n, 2)
|
29
29
|
|
30
30
|
@name, @value = parse_query(@raw, ';').to_a.first
|
31
|
-
@options = parse_query(options, ';')
|
31
|
+
@options = Hash[parse_query(options, ';').map { |k, v| [k.downcase, v] }]
|
32
32
|
|
33
|
-
if @options['domain']
|
33
|
+
if domain = @options['domain']
|
34
34
|
@exact_domain_match = false
|
35
|
+
domain[0] = '' if domain[0] == '.'
|
35
36
|
else
|
36
37
|
# If the domain attribute is not present in the cookie,
|
37
38
|
# the domain must match exactly.
|
@@ -68,7 +69,7 @@ module Rack
|
|
68
69
|
# Whether the cookie has the httponly flag, indicating it is not available via
|
69
70
|
# a javascript API.
|
70
71
|
def http_only?
|
71
|
-
@options.key?('
|
72
|
+
@options.key?('httponly')
|
72
73
|
end
|
73
74
|
|
74
75
|
# The explicit or implicit path for the cookie.
|
@@ -92,15 +93,13 @@ module Rack
|
|
92
93
|
|
93
94
|
uri.host = @default_host if uri.host.nil?
|
94
95
|
|
95
|
-
real_domain = domain =~ /^\./ ? domain[1..-1] : domain
|
96
96
|
!!((!secure? || (secure? && uri.scheme == 'https')) &&
|
97
|
-
uri.host =~ Regexp.new("#{'^' if @exact_domain_match}#{Regexp.escape(
|
98
|
-
uri.path =~ Regexp.new("^#{Regexp.escape(path)}"))
|
97
|
+
uri.host =~ Regexp.new("#{'^' if @exact_domain_match}#{Regexp.escape(domain)}$", Regexp::IGNORECASE))
|
99
98
|
end
|
100
99
|
|
101
100
|
# Cookies that do not match the URI will not be sent in requests to the URI.
|
102
101
|
def matches?(uri)
|
103
|
-
!expired? && valid?(uri)
|
102
|
+
!expired? && valid?(uri) && uri.path.start_with?(path)
|
104
103
|
end
|
105
104
|
|
106
105
|
# Order cookies by name, path, and domain.
|
@@ -110,11 +109,13 @@ module Rack
|
|
110
109
|
|
111
110
|
# A hash of cookie options, including the cookie value, but excluding the cookie name.
|
112
111
|
def to_h
|
113
|
-
@options.merge(
|
112
|
+
hash = @options.merge(
|
114
113
|
'value' => @value,
|
115
114
|
'HttpOnly' => http_only?,
|
116
115
|
'secure' => secure?
|
117
116
|
)
|
117
|
+
hash.delete('httponly')
|
118
|
+
hash
|
118
119
|
end
|
119
120
|
alias to_hash to_h
|
120
121
|
|
@@ -138,6 +139,12 @@ module Rack
|
|
138
139
|
@cookies = cookies.sort!
|
139
140
|
end
|
140
141
|
|
142
|
+
# Ensure the copy uses a distinct cookies array.
|
143
|
+
def initialize_copy(other)
|
144
|
+
super
|
145
|
+
@cookies = @cookies.dup
|
146
|
+
end
|
147
|
+
|
141
148
|
# Return the value for first cookie with the given name, or nil
|
142
149
|
# if no such cookie exists.
|
143
150
|
def [](name)
|
@@ -177,12 +184,10 @@ module Rack
|
|
177
184
|
def merge(raw_cookies, uri = nil)
|
178
185
|
return unless raw_cookies
|
179
186
|
|
180
|
-
if raw_cookies.is_a? String
|
181
|
-
raw_cookies = raw_cookies.split("\n")
|
182
|
-
raw_cookies.reject!(&:empty?)
|
183
|
-
end
|
187
|
+
raw_cookies = raw_cookies.split("\n") if raw_cookies.is_a? String
|
184
188
|
|
185
189
|
raw_cookies.each do |raw_cookie|
|
190
|
+
next if raw_cookie.empty?
|
186
191
|
cookie = Cookie.new(raw_cookie, uri, @default_host)
|
187
192
|
self << cookie if cookie.valid?(uri)
|
188
193
|
end
|
data/lib/rack/test/methods.rb
CHANGED
@@ -42,7 +42,11 @@ module Rack
|
|
42
42
|
# Backwards compatibility for capybara
|
43
43
|
build_rack_mock_session
|
44
44
|
else
|
45
|
-
|
45
|
+
if respond_to?(:default_host)
|
46
|
+
Session.new(app, default_host)
|
47
|
+
else
|
48
|
+
Session.new(app)
|
49
|
+
end
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
@@ -61,11 +65,6 @@ module Rack
|
|
61
65
|
@_rack_test_current_session = session
|
62
66
|
end
|
63
67
|
|
64
|
-
def digest_authorize(username, password) # :nodoc:
|
65
|
-
warn 'digest authentication support will be removed in rack-test 2.1', uplevel: 1
|
66
|
-
current_session._digest_authorize(username, password)
|
67
|
-
end
|
68
|
-
|
69
68
|
def_delegators(:current_session,
|
70
69
|
:request,
|
71
70
|
:get,
|
@@ -27,16 +27,18 @@ module Rack
|
|
27
27
|
# content :: is a path to a file, or an {IO} or {StringIO} object representing the content.
|
28
28
|
# content_type :: MIME type of the file
|
29
29
|
# binary :: Whether the file should be set to binmode (content treated as binary).
|
30
|
-
# original_filename :: The filename to use for the file if
|
30
|
+
# original_filename :: The filename to use for the file. Required if content is StringIO, optional override if not
|
31
31
|
def initialize(content, content_type = 'text/plain', binary = false, original_filename: nil)
|
32
|
+
@content_type = content_type
|
33
|
+
@original_filename = original_filename
|
34
|
+
|
32
35
|
case content
|
33
36
|
when StringIO
|
34
|
-
initialize_from_stringio(content
|
37
|
+
initialize_from_stringio(content)
|
35
38
|
else
|
36
39
|
initialize_from_file_path(content)
|
37
40
|
end
|
38
41
|
|
39
|
-
@content_type = content_type
|
40
42
|
@tempfile.binmode if binary
|
41
43
|
end
|
42
44
|
|
@@ -70,38 +72,26 @@ module Rack
|
|
70
72
|
tempfile.respond_to?(method_name, include_private) || super
|
71
73
|
end
|
72
74
|
|
73
|
-
# A proc that can be used as a finalizer to close and unlink the tempfile.
|
74
|
-
def self.finalize(file)
|
75
|
-
proc { actually_finalize file }
|
76
|
-
end
|
77
|
-
|
78
|
-
# Close and unlink the given file, used as a finalizer for the tempfile,
|
79
|
-
# if the tempfile is backed by a file in the filesystem.
|
80
|
-
def self.actually_finalize(file)
|
81
|
-
file.close
|
82
|
-
file.unlink
|
83
|
-
end
|
84
|
-
|
85
75
|
private
|
86
76
|
|
87
77
|
# Use the StringIO as the tempfile.
|
88
|
-
def initialize_from_stringio(stringio
|
78
|
+
def initialize_from_stringio(stringio)
|
79
|
+
raise(ArgumentError, 'Missing `original_filename` for StringIO object') unless @original_filename
|
80
|
+
|
89
81
|
@tempfile = stringio
|
90
|
-
@original_filename = original_filename || raise(ArgumentError, 'Missing `original_filename` for StringIO object')
|
91
82
|
end
|
92
83
|
|
93
|
-
# Create a tempfile and copy the content from the given path into the tempfile
|
84
|
+
# Create a tempfile and copy the content from the given path into the tempfile, optionally renaming if
|
85
|
+
# original_filename has been set.
|
94
86
|
def initialize_from_file_path(path)
|
95
87
|
raise "#{path} file does not exist" unless ::File.exist?(path)
|
96
88
|
|
97
|
-
@original_filename
|
89
|
+
@original_filename ||= ::File.basename(path)
|
98
90
|
extension = ::File.extname(@original_filename)
|
99
91
|
|
100
92
|
@tempfile = Tempfile.new([::File.basename(@original_filename, extension), extension])
|
101
93
|
@tempfile.set_encoding(Encoding::BINARY)
|
102
94
|
|
103
|
-
ObjectSpace.define_finalizer(self, self.class.finalize(@tempfile))
|
104
|
-
|
105
95
|
FileUtils.copy_file(path, @tempfile.path)
|
106
96
|
end
|
107
97
|
end
|
data/lib/rack/test/version.rb
CHANGED
data/lib/rack/test.rb
CHANGED
@@ -98,8 +98,6 @@ module Rack
|
|
98
98
|
# If a block is given, #last_response is also yielded to the block.
|
99
99
|
def initialize(app, default_host = DEFAULT_HOST)
|
100
100
|
@env = {}
|
101
|
-
@digest_username = nil
|
102
|
-
@digest_password = nil
|
103
101
|
@app = app
|
104
102
|
@after_request = []
|
105
103
|
@default_host = default_host
|
@@ -204,21 +202,6 @@ module Rack
|
|
204
202
|
|
205
203
|
alias authorize basic_authorize
|
206
204
|
|
207
|
-
# Set the username and password for HTTP Digest authorization, to be
|
208
|
-
# included in subsequent requests in the HTTP_AUTHORIZATION header.
|
209
|
-
# This method is deprecated and will be removed in rack-test 2.1
|
210
|
-
#
|
211
|
-
# Example:
|
212
|
-
# digest_authorize "bryan", "secret"
|
213
|
-
def digest_authorize(username, password)
|
214
|
-
warn 'digest authentication support will be removed in rack-test 2.1', uplevel: 1
|
215
|
-
_digest_authorize(username, password)
|
216
|
-
end
|
217
|
-
def _digest_authorize(username, password) # :nodoc:
|
218
|
-
@digest_username = username
|
219
|
-
@digest_password = password
|
220
|
-
end
|
221
|
-
|
222
205
|
# Rack::Test will not follow any redirects automatically. This method
|
223
206
|
# will follow the redirect returned (including setting the Referer header
|
224
207
|
# on the new request) in the last response. If the last response was not
|
@@ -251,6 +234,25 @@ module Rack
|
|
251
234
|
)
|
252
235
|
end
|
253
236
|
|
237
|
+
# Yield to the block, and restore the last request, last response, and
|
238
|
+
# cookie jar to the state they were prior to block execution upon
|
239
|
+
# exiting the block.
|
240
|
+
def restore_state
|
241
|
+
request = @last_request
|
242
|
+
response = @last_response
|
243
|
+
cookie_jar = @cookie_jar.dup
|
244
|
+
after_request = @after_request.dup
|
245
|
+
|
246
|
+
begin
|
247
|
+
yield
|
248
|
+
ensure
|
249
|
+
@last_request = request
|
250
|
+
@last_response = response
|
251
|
+
@cookie_jar = cookie_jar
|
252
|
+
@after_request = after_request
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
254
256
|
private
|
255
257
|
|
256
258
|
# :nocov:
|
@@ -310,7 +312,7 @@ module Rack
|
|
310
312
|
multipart = env.has_key?(:multipart) ? env.delete(:multipart) : env['CONTENT_TYPE'].start_with?('multipart/')
|
311
313
|
|
312
314
|
if params.is_a?(Hash)
|
313
|
-
if data = build_multipart(params, false, multipart)
|
315
|
+
if !params.empty? && data = build_multipart(params, false, multipart)
|
314
316
|
env[:input] = data
|
315
317
|
env['CONTENT_LENGTH'] ||= data.length.to_s
|
316
318
|
env['CONTENT_TYPE'] = "#{multipart_content_type(env)}; boundary=#{MULTIPART_BOUNDARY}"
|
@@ -363,43 +365,9 @@ module Rack
|
|
363
365
|
@after_request.each(&:call)
|
364
366
|
@last_response.finish
|
365
367
|
|
366
|
-
if
|
367
|
-
auth_env = env.merge('HTTP_AUTHORIZATION' => digest_auth_header,
|
368
|
-
'rack-test.digest_auth_retry' => true)
|
369
|
-
auth_env.delete('rack.request')
|
370
|
-
process_request(uri, auth_env)
|
371
|
-
else
|
372
|
-
yield last_response if block_given?
|
373
|
-
|
374
|
-
last_response
|
375
|
-
end
|
376
|
-
end
|
377
|
-
|
378
|
-
def digest_auth_header
|
379
|
-
require_relative 'test/mock_digest_request'
|
380
|
-
|
381
|
-
challenge = last_response['WWW-Authenticate'].split(' ', 2).last
|
382
|
-
params = Rack::Auth::Digest::Params.parse(challenge)
|
383
|
-
|
384
|
-
params.merge!('username' => @digest_username,
|
385
|
-
'nc' => '00000001',
|
386
|
-
'cnonce' => 'nonsensenonce',
|
387
|
-
'uri' => last_request.fullpath,
|
388
|
-
'method' => last_request.env['REQUEST_METHOD'])
|
389
|
-
|
390
|
-
params['response'] = MockDigestRequest_.new(params).response(@digest_password)
|
368
|
+
yield @last_response if block_given?
|
391
369
|
|
392
|
-
|
393
|
-
end
|
394
|
-
|
395
|
-
def retry_with_digest_auth?(env)
|
396
|
-
last_response.status == 401 &&
|
397
|
-
digest_auth_configured? &&
|
398
|
-
!env['rack-test.digest_auth_retry']
|
399
|
-
end
|
400
|
-
|
401
|
-
def digest_auth_configured?
|
402
|
-
@digest_username
|
370
|
+
@last_response
|
403
371
|
end
|
404
372
|
end
|
405
373
|
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-test
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
- Bryan Helmkamp
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-12-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -81,11 +81,9 @@ files:
|
|
81
81
|
- History.md
|
82
82
|
- MIT-LICENSE.txt
|
83
83
|
- README.md
|
84
|
-
- lib/rack/mock_session.rb
|
85
84
|
- lib/rack/test.rb
|
86
85
|
- lib/rack/test/cookie_jar.rb
|
87
86
|
- lib/rack/test/methods.rb
|
88
|
-
- lib/rack/test/mock_digest_request.rb
|
89
87
|
- lib/rack/test/uploaded_file.rb
|
90
88
|
- lib/rack/test/utils.rb
|
91
89
|
- lib/rack/test/version.rb
|
@@ -97,7 +95,7 @@ metadata:
|
|
97
95
|
bug_tracker_uri: https://github.com/rack/rack-test/issues
|
98
96
|
mailing_list_uri: https://github.com/rack/rack-test/discussions
|
99
97
|
changelog_uri: https://github.com/rack/rack-test/blob/main/History.md
|
100
|
-
post_install_message:
|
98
|
+
post_install_message:
|
101
99
|
rdoc_options: []
|
102
100
|
require_paths:
|
103
101
|
- lib
|
@@ -112,8 +110,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
110
|
- !ruby/object:Gem::Version
|
113
111
|
version: '0'
|
114
112
|
requirements: []
|
115
|
-
rubygems_version: 3.
|
116
|
-
signing_key:
|
113
|
+
rubygems_version: 3.5.22
|
114
|
+
signing_key:
|
117
115
|
specification_version: 4
|
118
116
|
summary: Simple testing API built on Rack
|
119
117
|
test_files: []
|
data/lib/rack/mock_session.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# :nocov:
|
4
|
-
require 'rack/auth/digest' unless defined?(Rack::Auth::Digest)
|
5
|
-
# :nocov:
|
6
|
-
|
7
|
-
module Rack
|
8
|
-
module Test
|
9
|
-
class MockDigestRequest_ # :nodoc:
|
10
|
-
def initialize(params)
|
11
|
-
@params = params
|
12
|
-
end
|
13
|
-
|
14
|
-
def method_missing(sym)
|
15
|
-
if @params.key? k = sym.to_s
|
16
|
-
return @params[k]
|
17
|
-
end
|
18
|
-
|
19
|
-
super
|
20
|
-
end
|
21
|
-
|
22
|
-
def method
|
23
|
-
@params['method']
|
24
|
-
end
|
25
|
-
|
26
|
-
def response(password)
|
27
|
-
Rack::Auth::Digest::MD5.new(nil).send :digest, self, password
|
28
|
-
end
|
29
|
-
end
|
30
|
-
MockDigestRequest = MockDigestRequest_
|
31
|
-
# :nocov:
|
32
|
-
deprecate_constant :MockDigestRequest if respond_to?(:deprecate_constant, true)
|
33
|
-
# :nocov:
|
34
|
-
end
|
35
|
-
end
|