rack 2.0.0.rc1 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/SPEC +2 -2
- data/lib/rack.rb +1 -1
- data/lib/rack/auth/abstract/request.rb +5 -1
- data/lib/rack/deflater.rb +2 -37
- data/lib/rack/file.rb +1 -1
- data/lib/rack/handler/webrick.rb +4 -4
- data/lib/rack/lint.rb +2 -2
- data/lib/rack/method_override.rb +3 -0
- data/lib/rack/mock.rb +1 -2
- data/lib/rack/multipart/parser.rb +1 -1
- data/lib/rack/query_parser.rb +13 -2
- data/lib/rack/request.rb +2 -2
- data/lib/rack/response.rb +1 -1
- data/lib/rack/server.rb +2 -1
- data/lib/rack/session/abstract/id.rb +13 -3
- data/lib/rack/utils.rb +1 -1
- data/rack.gemspec +0 -2
- data/test/multipart/filename_with_null_byte +7 -0
- data/test/spec_auth_basic.rb +7 -0
- data/test/spec_chunked.rb +1 -1
- data/test/spec_content_length.rb +4 -4
- data/test/spec_content_type.rb +1 -1
- data/test/spec_deflater.rb +24 -14
- data/test/spec_etag.rb +1 -1
- data/test/spec_file.rb +16 -3
- data/test/spec_lint.rb +2 -2
- data/test/spec_media_type.rb +1 -1
- data/test/spec_method_override.rb +17 -4
- data/test/spec_mime.rb +1 -1
- data/test/spec_multipart.rb +9 -3
- data/test/spec_request.rb +12 -12
- data/test/spec_response.rb +5 -5
- data/test/spec_server.rb +2 -2
- data/test/spec_session_abstract_session_hash.rb +17 -0
- data/test/spec_session_cookie.rb +5 -5
- data/test/spec_session_memcache.rb +3 -3
- data/test/spec_session_pool.rb +1 -1
- data/test/spec_static.rb +2 -2
- data/test/spec_utils.rb +24 -12
- data/test/spec_webrick.rb +3 -2
- metadata +6 -21
- data/test/cgi/lighttpd.errors +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8fee84474048108cce439e6089d87176a6870bc2
|
4
|
+
data.tar.gz: 0ed86a0e0e70541873ffa31dfef66e5268a107b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 460ecadb871f77085e040982f9cb56fd2fd165f95d172c4ff73b3d16c899dc26f0e8a352667044dd32b34a57d3a179efe65f3b933c58adf7b0427566a6356188
|
7
|
+
data.tar.gz: 1ab651dc52e8ff7ace49f22359aff5c7d2baff1787082398c7cf21aa593552183872466b3cf03e6675ca1621e44076e85cddae9486713311412e916baee5bac1
|
data/SPEC
CHANGED
@@ -237,10 +237,10 @@ consisting of lines (for multiple header values, e.g. multiple
|
|
237
237
|
The lines must not contain characters below 037.
|
238
238
|
=== The Content-Type
|
239
239
|
There must not be a <tt>Content-Type</tt>, when the +Status+ is 1xx,
|
240
|
-
204
|
240
|
+
204 or 304.
|
241
241
|
=== The Content-Length
|
242
242
|
There must not be a <tt>Content-Length</tt> header when the
|
243
|
-
+Status+ is 1xx, 204
|
243
|
+
+Status+ is 1xx, 204 or 304.
|
244
244
|
=== The Body
|
245
245
|
The Body must respond to +each+
|
246
246
|
and must only yield String values.
|
data/lib/rack.rb
CHANGED
data/lib/rack/deflater.rb
CHANGED
@@ -8,7 +8,6 @@ module Rack
|
|
8
8
|
# Currently supported compression algorithms:
|
9
9
|
#
|
10
10
|
# * gzip
|
11
|
-
# * deflate
|
12
11
|
# * identity (no transformation)
|
13
12
|
#
|
14
13
|
# The middleware automatically detects when compression is supported
|
@@ -22,7 +21,7 @@ module Rack
|
|
22
21
|
# [app] rack app instance
|
23
22
|
# [options] hash of deflater options, i.e.
|
24
23
|
# 'if' - a lambda enabling / disabling deflation based on returned boolean value
|
25
|
-
# e.g use Rack::Deflater, :if => lambda { |env, status, headers, body| body.
|
24
|
+
# e.g use Rack::Deflater, :if => lambda { |env, status, headers, body| body.map(&:bytesize).reduce(0, :+) > 512 }
|
26
25
|
# 'include' - a list of content types that should be compressed
|
27
26
|
def initialize(app, options = {})
|
28
27
|
@app = app
|
@@ -41,7 +40,7 @@ module Rack
|
|
41
40
|
|
42
41
|
request = Request.new(env)
|
43
42
|
|
44
|
-
encoding = Utils.select_best_encoding(%w(gzip
|
43
|
+
encoding = Utils.select_best_encoding(%w(gzip identity),
|
45
44
|
request.accept_encoding)
|
46
45
|
|
47
46
|
# Set the Vary HTTP header.
|
@@ -57,10 +56,6 @@ module Rack
|
|
57
56
|
mtime = headers.key?("Last-Modified") ?
|
58
57
|
Time.httpdate(headers["Last-Modified"]) : Time.now
|
59
58
|
[status, headers, GzipStream.new(body, mtime)]
|
60
|
-
when "deflate"
|
61
|
-
headers['Content-Encoding'] = "deflate"
|
62
|
-
headers.delete(CONTENT_LENGTH)
|
63
|
-
[status, headers, DeflateStream.new(body)]
|
64
59
|
when "identity"
|
65
60
|
[status, headers, body]
|
66
61
|
when nil
|
@@ -101,36 +96,6 @@ module Rack
|
|
101
96
|
end
|
102
97
|
end
|
103
98
|
|
104
|
-
class DeflateStream
|
105
|
-
DEFLATE_ARGS = [
|
106
|
-
Zlib::DEFAULT_COMPRESSION,
|
107
|
-
# drop the zlib header which causes both Safari and IE to choke
|
108
|
-
-Zlib::MAX_WBITS,
|
109
|
-
Zlib::DEF_MEM_LEVEL,
|
110
|
-
Zlib::DEFAULT_STRATEGY
|
111
|
-
]
|
112
|
-
|
113
|
-
def initialize(body)
|
114
|
-
@body = body
|
115
|
-
@closed = false
|
116
|
-
end
|
117
|
-
|
118
|
-
def each
|
119
|
-
deflator = ::Zlib::Deflate.new(*DEFLATE_ARGS)
|
120
|
-
@body.each { |part| yield deflator.deflate(part, Zlib::SYNC_FLUSH) }
|
121
|
-
yield fin = deflator.finish
|
122
|
-
ensure
|
123
|
-
deflator.finish unless fin
|
124
|
-
deflator.close
|
125
|
-
end
|
126
|
-
|
127
|
-
def close
|
128
|
-
return if @closed
|
129
|
-
@closed = true
|
130
|
-
@body.close if @body.respond_to?(:close)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
99
|
private
|
135
100
|
|
136
101
|
def should_deflate?(env, status, headers, body)
|
data/lib/rack/file.rb
CHANGED
@@ -158,7 +158,7 @@ module Rack
|
|
158
158
|
|
159
159
|
def filesize path
|
160
160
|
# If response_body is present, use its size.
|
161
|
-
return
|
161
|
+
return response_body.bytesize if response_body
|
162
162
|
|
163
163
|
# We check via File::size? whether this file provides size info
|
164
164
|
# via stat (e.g. /proc files often don't), otherwise we have to
|
data/lib/rack/handler/webrick.rb
CHANGED
@@ -86,10 +86,11 @@ module Rack
|
|
86
86
|
status, headers, body = @app.call(env)
|
87
87
|
begin
|
88
88
|
res.status = status.to_i
|
89
|
+
io_lambda = nil
|
89
90
|
headers.each { |k, vs|
|
90
|
-
|
91
|
-
|
92
|
-
|
91
|
+
if k == RACK_HIJACK
|
92
|
+
io_lambda = vs
|
93
|
+
elsif k.downcase == "set-cookie"
|
93
94
|
res.cookies.concat vs.split("\n")
|
94
95
|
else
|
95
96
|
# Since WEBrick won't accept repeated headers,
|
@@ -98,7 +99,6 @@ module Rack
|
|
98
99
|
end
|
99
100
|
}
|
100
101
|
|
101
|
-
io_lambda = headers[RACK_HIJACK]
|
102
102
|
if io_lambda
|
103
103
|
rd, wr = IO.pipe
|
104
104
|
res.body = rd
|
data/lib/rack/lint.rb
CHANGED
@@ -659,7 +659,7 @@ module Rack
|
|
659
659
|
def check_content_type(status, headers)
|
660
660
|
headers.each { |key, value|
|
661
661
|
## There must not be a <tt>Content-Type</tt>, when the +Status+ is 1xx,
|
662
|
-
## 204
|
662
|
+
## 204 or 304.
|
663
663
|
if key.downcase == "content-type"
|
664
664
|
assert("Content-Type header found in #{status} response, not allowed") {
|
665
665
|
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
|
@@ -674,7 +674,7 @@ module Rack
|
|
674
674
|
headers.each { |key, value|
|
675
675
|
if key.downcase == 'content-length'
|
676
676
|
## There must not be a <tt>Content-Length</tt> header when the
|
677
|
-
## +Status+ is 1xx, 204
|
677
|
+
## +Status+ is 1xx, 204 or 304.
|
678
678
|
assert("Content-Length header found in #{status} response, not allowed") {
|
679
679
|
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
|
680
680
|
}
|
data/lib/rack/method_override.rb
CHANGED
@@ -38,6 +38,9 @@ module Rack
|
|
38
38
|
def method_override_param(req)
|
39
39
|
req.POST[METHOD_OVERRIDE_PARAM_KEY]
|
40
40
|
rescue Utils::InvalidParameterError, Utils::ParameterTypeError
|
41
|
+
req.get_header(RACK_ERRORS).puts "Invalid or incomplete POST params"
|
42
|
+
rescue EOFError
|
43
|
+
req.get_header(RACK_ERRORS).puts "Bad request content body"
|
41
44
|
end
|
42
45
|
end
|
43
46
|
end
|
data/lib/rack/mock.rb
CHANGED
@@ -163,7 +163,6 @@ module Rack
|
|
163
163
|
def initialize(status, headers, body, errors=StringIO.new(""))
|
164
164
|
@original_headers = headers
|
165
165
|
@errors = errors.string if errors.respond_to?(:string)
|
166
|
-
@body_string = nil
|
167
166
|
|
168
167
|
super(body, status, headers)
|
169
168
|
end
|
@@ -191,7 +190,7 @@ module Rack
|
|
191
190
|
end
|
192
191
|
|
193
192
|
def empty?
|
194
|
-
[201, 204,
|
193
|
+
[201, 204, 304].include? status
|
195
194
|
end
|
196
195
|
end
|
197
196
|
end
|
@@ -8,7 +8,7 @@ module Rack
|
|
8
8
|
BUFSIZE = 16384
|
9
9
|
TEXT_PLAIN = "text/plain"
|
10
10
|
TEMPFILE_FACTORY = lambda { |filename, content_type|
|
11
|
-
Tempfile.new(["RackMultipart", ::File.extname(filename)])
|
11
|
+
Tempfile.new(["RackMultipart", ::File.extname(filename.gsub("\0".freeze, '%00'.freeze))])
|
12
12
|
}
|
13
13
|
|
14
14
|
class BoundedIO # :nodoc:
|
data/lib/rack/query_parser.rb
CHANGED
@@ -102,8 +102,7 @@ module Rack
|
|
102
102
|
child_key = $1
|
103
103
|
params[k] ||= []
|
104
104
|
raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
|
105
|
-
|
106
|
-
if params_hash_type?(params[k].last) && !params[k].last.key?(first_key)
|
105
|
+
if params_hash_type?(params[k].last) && !params_hash_has_key?(params[k].last, child_key)
|
107
106
|
normalize_params(params[k].last, child_key, v, depth - 1)
|
108
107
|
else
|
109
108
|
params[k] << normalize_params(make_params, child_key, v, depth - 1)
|
@@ -135,6 +134,18 @@ module Rack
|
|
135
134
|
obj.kind_of?(@params_class)
|
136
135
|
end
|
137
136
|
|
137
|
+
def params_hash_has_key?(hash, key)
|
138
|
+
return false if key =~ /\[\]/
|
139
|
+
|
140
|
+
key.split(/[\[\]]+/).inject(hash) do |h, part|
|
141
|
+
next h if part == ''
|
142
|
+
return false unless params_hash_type?(h) && h.key?(part)
|
143
|
+
h[part]
|
144
|
+
end
|
145
|
+
|
146
|
+
true
|
147
|
+
end
|
148
|
+
|
138
149
|
def unescape(s)
|
139
150
|
Utils.unescape(s)
|
140
151
|
end
|
data/lib/rack/request.rb
CHANGED
@@ -422,7 +422,7 @@ module Rack
|
|
422
422
|
|
423
423
|
# shortcut for <tt>request.params[key]</tt>
|
424
424
|
def [](key)
|
425
|
-
if $
|
425
|
+
if $VERBOSE
|
426
426
|
warn("Request#[] is deprecated and will be removed in a future version of Rack. Please use request.params[] instead")
|
427
427
|
end
|
428
428
|
|
@@ -433,7 +433,7 @@ module Rack
|
|
433
433
|
#
|
434
434
|
# Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params.
|
435
435
|
def []=(key, value)
|
436
|
-
if $
|
436
|
+
if $VERBOSE
|
437
437
|
warn("Request#[]= is deprecated and will be removed in a future version of Rack. Please use request.params[]= instead")
|
438
438
|
end
|
439
439
|
|
data/lib/rack/response.rb
CHANGED
data/lib/rack/server.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'optparse'
|
2
|
+
require 'fileutils'
|
2
3
|
|
3
4
|
|
4
5
|
module Rack
|
@@ -359,7 +360,7 @@ module Rack
|
|
359
360
|
|
360
361
|
def write_pid
|
361
362
|
::File.open(options[:pid], ::File::CREAT | ::File::EXCL | ::File::WRONLY ){ |f| f.write("#{Process.pid}") }
|
362
|
-
at_exit { ::
|
363
|
+
at_exit { ::FileUtils.rm_f(options[:pid]) }
|
363
364
|
rescue Errno::EEXIST
|
364
365
|
check_pid!
|
365
366
|
retry
|
@@ -18,6 +18,8 @@ module Rack
|
|
18
18
|
include Enumerable
|
19
19
|
attr_writer :id
|
20
20
|
|
21
|
+
Unspecified = Object.new
|
22
|
+
|
21
23
|
def self.find(req)
|
22
24
|
req.get_header RACK_SESSION
|
23
25
|
end
|
@@ -54,7 +56,15 @@ module Rack
|
|
54
56
|
load_for_read!
|
55
57
|
@data[key.to_s]
|
56
58
|
end
|
57
|
-
|
59
|
+
|
60
|
+
def fetch(key, default=Unspecified, &block)
|
61
|
+
load_for_read!
|
62
|
+
if default == Unspecified
|
63
|
+
@data.fetch(key.to_s, &block)
|
64
|
+
else
|
65
|
+
@data.fetch(key.to_s, default, &block)
|
66
|
+
end
|
67
|
+
end
|
58
68
|
|
59
69
|
def has_key?(key)
|
60
70
|
load_for_read!
|
@@ -167,7 +177,7 @@ module Rack
|
|
167
177
|
# * :key determines the name of the cookie, by default it is
|
168
178
|
# 'rack.session'
|
169
179
|
# * :path, :domain, :expire_after, :secure, and :httponly set the related
|
170
|
-
# cookie options as by Rack::Response#
|
180
|
+
# cookie options as by Rack::Response#set_cookie
|
171
181
|
# * :skip will not a set a cookie in the response nor update the session state
|
172
182
|
# * :defer will not set a cookie in the response but still update the session
|
173
183
|
# state if it is used with a backend
|
@@ -200,7 +210,7 @@ module Rack
|
|
200
210
|
:sidbits => 128,
|
201
211
|
:cookie_only => true,
|
202
212
|
:secure_random => ::SecureRandom
|
203
|
-
}
|
213
|
+
}.freeze
|
204
214
|
|
205
215
|
attr_reader :key, :default_options, :sid_secure
|
206
216
|
|
data/lib/rack/utils.rb
CHANGED
@@ -576,7 +576,7 @@ module Rack
|
|
576
576
|
}
|
577
577
|
|
578
578
|
# Responses with HTTP status codes that should not have an entity body
|
579
|
-
STATUS_WITH_NO_ENTITY_BODY = Set.new((100..199).to_a << 204 <<
|
579
|
+
STATUS_WITH_NO_ENTITY_BODY = Set.new((100..199).to_a << 204 << 304)
|
580
580
|
|
581
581
|
SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map { |code, message|
|
582
582
|
[message.downcase.gsub(/\s|-|'/, '_').to_sym, code]
|
data/rack.gemspec
CHANGED
@@ -28,8 +28,6 @@ EOF
|
|
28
28
|
s.homepage = 'http://rack.github.io/'
|
29
29
|
s.required_ruby_version = '>= 2.2.2'
|
30
30
|
|
31
|
-
s.add_dependency 'json'
|
32
|
-
|
33
31
|
s.add_development_dependency 'minitest', "~> 5.0"
|
34
32
|
s.add_development_dependency 'minitest-sprint'
|
35
33
|
s.add_development_dependency 'concurrent-ruby'
|
data/test/spec_auth_basic.rb
CHANGED
@@ -75,6 +75,13 @@ describe Rack::Auth::Basic do
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
it 'return 401 Bad Request for a nil authorization header' do
|
79
|
+
request 'HTTP_AUTHORIZATION' => nil do |response|
|
80
|
+
response.must_be :client_error?
|
81
|
+
response.status.must_equal 401
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
78
85
|
it 'takes realm as optional constructor arg' do
|
79
86
|
app = Rack::Auth::Basic.new(unprotected_app, realm) { true }
|
80
87
|
realm.must_equal app.realm
|
data/test/spec_chunked.rb
CHANGED
@@ -92,7 +92,7 @@ describe Rack::Chunked do
|
|
92
92
|
body.join.must_equal 'Hello World!'
|
93
93
|
end
|
94
94
|
|
95
|
-
[100, 204,
|
95
|
+
[100, 204, 304].each do |status_code|
|
96
96
|
it "not modify response when status code is #{status_code}" do
|
97
97
|
app = lambda { |env| [status_code, {}, []] }
|
98
98
|
status, headers, _ = chunked(app).call(@env)
|
data/test/spec_content_length.rb
CHANGED
@@ -36,13 +36,13 @@ describe Rack::ContentLength do
|
|
36
36
|
it "not set Content-Length on 304 responses" do
|
37
37
|
app = lambda { |env| [304, {}, []] }
|
38
38
|
response = content_length(app).call(request)
|
39
|
-
response[1]['Content-Length'].
|
39
|
+
response[1]['Content-Length'].must_be_nil
|
40
40
|
end
|
41
41
|
|
42
42
|
it "not set Content-Length when Transfer-Encoding is chunked" do
|
43
43
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Transfer-Encoding' => 'chunked'}, []] }
|
44
44
|
response = content_length(app).call(request)
|
45
|
-
response[1]['Content-Length'].
|
45
|
+
response[1]['Content-Length'].must_be_nil
|
46
46
|
end
|
47
47
|
|
48
48
|
# Using "Connection: close" for this is fairly contended. It might be useful
|
@@ -51,7 +51,7 @@ describe Rack::ContentLength do
|
|
51
51
|
# should "not force a Content-Length when Connection:close" do
|
52
52
|
# app = lambda { |env| [200, {'Connection' => 'close'}, []] }
|
53
53
|
# response = content_length(app).call({})
|
54
|
-
# response[1]['Content-Length'].
|
54
|
+
# response[1]['Content-Length'].must_be_nil
|
55
55
|
# end
|
56
56
|
|
57
57
|
it "close bodies that need to be closed" do
|
@@ -64,7 +64,7 @@ describe Rack::ContentLength do
|
|
64
64
|
|
65
65
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
|
66
66
|
response = content_length(app).call(request)
|
67
|
-
body.closed.
|
67
|
+
body.closed.must_be_nil
|
68
68
|
response[2].close
|
69
69
|
body.closed.must_equal true
|
70
70
|
end
|
data/test/spec_content_type.rb
CHANGED
@@ -41,6 +41,6 @@ describe Rack::ContentType do
|
|
41
41
|
it "not set Content-Type on 304 responses" do
|
42
42
|
app = lambda { |env| [304, {}, []] }
|
43
43
|
response = content_type(app, "text/html").call(request)
|
44
|
-
response[1]['Content-Type'].
|
44
|
+
response[1]['Content-Type'].must_be_nil
|
45
45
|
end
|
46
46
|
end
|
data/test/spec_deflater.rb
CHANGED
@@ -81,13 +81,22 @@ describe Rack::Deflater do
|
|
81
81
|
yield(status, headers, body) if block_given?
|
82
82
|
end
|
83
83
|
|
84
|
+
# automatic gzip detection (streamable)
|
85
|
+
def auto_inflater
|
86
|
+
Zlib::Inflate.new(32 + Zlib::MAX_WBITS)
|
87
|
+
end
|
88
|
+
|
89
|
+
def deflate_or_gzip
|
90
|
+
{'deflate, gzip' => 'gzip'}
|
91
|
+
end
|
92
|
+
|
84
93
|
it 'be able to deflate bodies that respond to each' do
|
85
94
|
app_body = Object.new
|
86
95
|
class << app_body; def each; yield('foo'); yield('bar'); end; end
|
87
96
|
|
88
|
-
verify(200, 'foobar',
|
97
|
+
verify(200, 'foobar', deflate_or_gzip, { 'app_body' => app_body }) do |status, headers, body|
|
89
98
|
headers.must_equal({
|
90
|
-
'Content-Encoding' => '
|
99
|
+
'Content-Encoding' => 'gzip',
|
91
100
|
'Vary' => 'Accept-Encoding',
|
92
101
|
'Content-Type' => 'text/plain'
|
93
102
|
})
|
@@ -98,15 +107,15 @@ describe Rack::Deflater do
|
|
98
107
|
app_body = Object.new
|
99
108
|
class << app_body; def each; yield('foo'); yield('bar'); end; end
|
100
109
|
|
101
|
-
verify(200, app_body,
|
110
|
+
verify(200, app_body, deflate_or_gzip, { 'skip_body_verify' => true }) do |status, headers, body|
|
102
111
|
headers.must_equal({
|
103
|
-
'Content-Encoding' => '
|
112
|
+
'Content-Encoding' => 'gzip',
|
104
113
|
'Vary' => 'Accept-Encoding',
|
105
114
|
'Content-Type' => 'text/plain'
|
106
115
|
})
|
107
116
|
|
108
117
|
buf = []
|
109
|
-
inflater =
|
118
|
+
inflater = auto_inflater
|
110
119
|
body.each { |part| buf << inflater.inflate(part) }
|
111
120
|
buf << inflater.finish
|
112
121
|
|
@@ -118,32 +127,33 @@ describe Rack::Deflater do
|
|
118
127
|
app_body = Object.new
|
119
128
|
class << app_body; def each; yield('foo'); yield('bar'); end; end
|
120
129
|
opts = { 'skip_body_verify' => true }
|
121
|
-
verify(200, app_body, '
|
130
|
+
verify(200, app_body, 'gzip', opts) do |status, headers, body|
|
122
131
|
headers.must_equal({
|
123
|
-
'Content-Encoding' => '
|
132
|
+
'Content-Encoding' => 'gzip',
|
124
133
|
'Vary' => 'Accept-Encoding',
|
125
134
|
'Content-Type' => 'text/plain'
|
126
135
|
})
|
127
136
|
|
128
137
|
buf = []
|
129
|
-
inflater =
|
138
|
+
inflater = auto_inflater
|
130
139
|
FakeDisconnect = Class.new(RuntimeError)
|
131
140
|
assert_raises(FakeDisconnect, "not Zlib::DataError not raised") do
|
132
141
|
body.each do |part|
|
133
|
-
|
142
|
+
tmp = inflater.inflate(part)
|
143
|
+
buf << tmp if tmp.bytesize > 0
|
134
144
|
raise FakeDisconnect
|
135
145
|
end
|
136
146
|
end
|
137
|
-
|
147
|
+
inflater.finish
|
138
148
|
buf.must_equal(%w(foo))
|
139
149
|
end
|
140
150
|
end
|
141
151
|
|
142
152
|
# TODO: This is really just a special case of the above...
|
143
153
|
it 'be able to deflate String bodies' do
|
144
|
-
verify(200, 'Hello world!',
|
154
|
+
verify(200, 'Hello world!', deflate_or_gzip) do |status, headers, body|
|
145
155
|
headers.must_equal({
|
146
|
-
'Content-Encoding' => '
|
156
|
+
'Content-Encoding' => 'gzip',
|
147
157
|
'Vary' => 'Accept-Encoding',
|
148
158
|
'Content-Type' => 'text/plain'
|
149
159
|
})
|
@@ -280,7 +290,7 @@ describe Rack::Deflater do
|
|
280
290
|
'Content-Encoding' => 'identity'
|
281
291
|
}
|
282
292
|
}
|
283
|
-
verify(200, 'Hello World!',
|
293
|
+
verify(200, 'Hello World!', deflate_or_gzip, options)
|
284
294
|
end
|
285
295
|
|
286
296
|
it "deflate if content-type matches :include" do
|
@@ -334,7 +344,7 @@ describe Rack::Deflater do
|
|
334
344
|
:if => lambda { |env, status, headers, body| true }
|
335
345
|
}
|
336
346
|
}
|
337
|
-
verify(200, 'Hello World!',
|
347
|
+
verify(200, 'Hello World!', deflate_or_gzip, options)
|
338
348
|
end
|
339
349
|
|
340
350
|
it "not deflate if :if lambda evaluates to false" do
|
data/test/spec_etag.rb
CHANGED
@@ -58,7 +58,7 @@ describe Rack::ETag do
|
|
58
58
|
it "not set Cache-Control if directive isn't present" do
|
59
59
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
|
60
60
|
response = etag(app, nil, nil).call(request)
|
61
|
-
response[1]['Cache-Control'].
|
61
|
+
response[1]['Cache-Control'].must_be_nil
|
62
62
|
end
|
63
63
|
|
64
64
|
it "not change ETag if it is already set" do
|
data/test/spec_file.rb
CHANGED
@@ -184,8 +184,8 @@ describe Rack::File do
|
|
184
184
|
status, heads, _ = file(DOCROOT).call(env)
|
185
185
|
|
186
186
|
status.must_equal 200
|
187
|
-
heads['Cache-Control'].
|
188
|
-
heads['Access-Control-Allow-Origin'].
|
187
|
+
heads['Cache-Control'].must_be_nil
|
188
|
+
heads['Access-Control-Allow-Origin'].must_be_nil
|
189
189
|
end
|
190
190
|
|
191
191
|
it "only support GET, HEAD, and OPTIONS requests" do
|
@@ -239,7 +239,7 @@ describe Rack::File do
|
|
239
239
|
req = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT, nil, nil)))
|
240
240
|
res = req.get "/cgi/test"
|
241
241
|
res.must_be :successful?
|
242
|
-
res['Content-Type'].
|
242
|
+
res['Content-Type'].must_be_nil
|
243
243
|
end
|
244
244
|
|
245
245
|
it "return error when file not found for head request" do
|
@@ -248,4 +248,17 @@ describe Rack::File do
|
|
248
248
|
res.body.must_be :empty?
|
249
249
|
end
|
250
250
|
|
251
|
+
class MyFile < Rack::File
|
252
|
+
def response_body
|
253
|
+
"hello world"
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
it "behaves gracefully if response_body is present" do
|
258
|
+
file = Rack::Lint.new MyFile.new(DOCROOT)
|
259
|
+
res = Rack::MockRequest.new(file).get("/cgi/test")
|
260
|
+
|
261
|
+
res.must_be :ok?
|
262
|
+
end
|
263
|
+
|
251
264
|
end
|
data/test/spec_lint.rb
CHANGED
@@ -269,7 +269,7 @@ describe Rack::Lint do
|
|
269
269
|
# }.must_raise(Rack::Lint::LintError).
|
270
270
|
# message.must_match(/No Content-Type/)
|
271
271
|
|
272
|
-
[100, 101, 204,
|
272
|
+
[100, 101, 204, 304].each do |status|
|
273
273
|
lambda {
|
274
274
|
Rack::Lint.new(lambda { |env|
|
275
275
|
[status, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
|
@@ -280,7 +280,7 @@ describe Rack::Lint do
|
|
280
280
|
end
|
281
281
|
|
282
282
|
it "notice content-length errors" do
|
283
|
-
[100, 101, 204,
|
283
|
+
[100, 101, 204, 304].each do |status|
|
284
284
|
lambda {
|
285
285
|
Rack::Lint.new(lambda { |env|
|
286
286
|
[status, {"Content-length" => "0"}, []]
|
data/test/spec_media_type.rb
CHANGED
@@ -66,14 +66,27 @@ EOF
|
|
66
66
|
"CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
|
67
67
|
"CONTENT_LENGTH" => input.size.to_s,
|
68
68
|
:method => "POST", :input => input)
|
69
|
-
|
70
|
-
app.call env
|
71
|
-
rescue EOFError
|
72
|
-
end
|
69
|
+
app.call env
|
73
70
|
|
74
71
|
env["REQUEST_METHOD"].must_equal "POST"
|
75
72
|
end
|
76
73
|
|
74
|
+
it "writes error to RACK_ERRORS when given invalid multipart form data" do
|
75
|
+
input = <<EOF
|
76
|
+
--AaB03x\r
|
77
|
+
content-disposition: form-data; name="huge"; filename="huge"\r
|
78
|
+
EOF
|
79
|
+
env = Rack::MockRequest.env_for("/",
|
80
|
+
"CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
|
81
|
+
"CONTENT_LENGTH" => input.size.to_s,
|
82
|
+
Rack::RACK_ERRORS => StringIO.new,
|
83
|
+
:method => "POST", :input => input)
|
84
|
+
Rack::MethodOverride.new(proc { [200, {"Content-Type" => "text/plain"}, []] }).call env
|
85
|
+
|
86
|
+
env[Rack::RACK_ERRORS].rewind
|
87
|
+
env[Rack::RACK_ERRORS].read.must_match /Bad request content body/
|
88
|
+
end
|
89
|
+
|
77
90
|
it "not modify REQUEST_METHOD for POST requests when the params are unparseable" do
|
78
91
|
env = Rack::MockRequest.env_for("/", :method => "POST", :input => "(%bad-params%)")
|
79
92
|
app.call env
|
data/test/spec_mime.rb
CHANGED
data/test/spec_multipart.rb
CHANGED
@@ -27,7 +27,7 @@ describe Rack::Multipart do
|
|
27
27
|
it "return nil if content type is not multipart" do
|
28
28
|
env = Rack::MockRequest.env_for("/",
|
29
29
|
"CONTENT_TYPE" => 'application/x-www-form-urlencoded')
|
30
|
-
Rack::Multipart.parse_multipart(env).
|
30
|
+
Rack::Multipart.parse_multipart(env).must_be_nil
|
31
31
|
end
|
32
32
|
|
33
33
|
it "parse multipart content when content type present but filename is not" do
|
@@ -305,11 +305,17 @@ describe Rack::Multipart do
|
|
305
305
|
params["files"][:filename].must_equal "bob's flowers.jpg"
|
306
306
|
end
|
307
307
|
|
308
|
+
it "parse multipart form with a null byte in the filename" do
|
309
|
+
env = Rack::MockRequest.env_for '/', multipart_fixture(:filename_with_null_byte)
|
310
|
+
params = Rack::Multipart.parse_multipart(env)
|
311
|
+
params["files"][:filename].must_equal "flowers.exe\u0000.jpg"
|
312
|
+
end
|
313
|
+
|
308
314
|
it "not include file params if no file was selected" do
|
309
315
|
env = Rack::MockRequest.env_for("/", multipart_fixture(:none))
|
310
316
|
params = Rack::Multipart.parse_multipart(env)
|
311
317
|
params["submit-name"].must_equal "Larry"
|
312
|
-
params["files"].
|
318
|
+
params["files"].must_be_nil
|
313
319
|
params.keys.wont_include "files"
|
314
320
|
end
|
315
321
|
|
@@ -557,7 +563,7 @@ Content-Type: image/jpeg\r
|
|
557
563
|
|
558
564
|
it "return nil if no UploadedFiles were used" do
|
559
565
|
data = Rack::Multipart.build_multipart("people" => [{"submit-name" => "Larry", "files" => "contents"}])
|
560
|
-
data.
|
566
|
+
data.must_be_nil
|
561
567
|
end
|
562
568
|
|
563
569
|
it "raise ArgumentError if params is not a Hash" do
|
data/test/spec_request.rb
CHANGED
@@ -476,7 +476,7 @@ class RackRequestTest < Minitest::Spec
|
|
476
476
|
|
477
477
|
req = make_request \
|
478
478
|
Rack::MockRequest.env_for("/")
|
479
|
-
req.referer.
|
479
|
+
req.referer.must_be_nil
|
480
480
|
end
|
481
481
|
|
482
482
|
it "extract user agent correctly" do
|
@@ -486,25 +486,25 @@ class RackRequestTest < Minitest::Spec
|
|
486
486
|
|
487
487
|
req = make_request \
|
488
488
|
Rack::MockRequest.env_for("/")
|
489
|
-
req.user_agent.
|
489
|
+
req.user_agent.must_be_nil
|
490
490
|
end
|
491
491
|
|
492
492
|
it "treat missing content type as nil" do
|
493
493
|
req = make_request \
|
494
494
|
Rack::MockRequest.env_for("/")
|
495
|
-
req.content_type.
|
495
|
+
req.content_type.must_be_nil
|
496
496
|
end
|
497
497
|
|
498
498
|
it "treat empty content type as nil" do
|
499
499
|
req = make_request \
|
500
500
|
Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "")
|
501
|
-
req.content_type.
|
501
|
+
req.content_type.must_be_nil
|
502
502
|
end
|
503
503
|
|
504
504
|
it "return nil media type for empty content type" do
|
505
505
|
req = make_request \
|
506
506
|
Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "")
|
507
|
-
req.media_type.
|
507
|
+
req.media_type.must_be_nil
|
508
508
|
end
|
509
509
|
|
510
510
|
it "cache, but invalidates the cache" do
|
@@ -1296,13 +1296,13 @@ EOF
|
|
1296
1296
|
req.trusted_proxy?('unix').must_equal 0
|
1297
1297
|
req.trusted_proxy?('unix:/tmp/sock').must_equal 0
|
1298
1298
|
|
1299
|
-
req.trusted_proxy?("unix.example.org").
|
1300
|
-
req.trusted_proxy?("example.org\n127.0.0.1").
|
1301
|
-
req.trusted_proxy?("127.0.0.1\nexample.org").
|
1302
|
-
req.trusted_proxy?("11.0.0.1").
|
1303
|
-
req.trusted_proxy?("172.15.0.1").
|
1304
|
-
req.trusted_proxy?("172.32.0.1").
|
1305
|
-
req.trusted_proxy?("2001:470:1f0b:18f8::1").
|
1299
|
+
req.trusted_proxy?("unix.example.org").must_be_nil
|
1300
|
+
req.trusted_proxy?("example.org\n127.0.0.1").must_be_nil
|
1301
|
+
req.trusted_proxy?("127.0.0.1\nexample.org").must_be_nil
|
1302
|
+
req.trusted_proxy?("11.0.0.1").must_be_nil
|
1303
|
+
req.trusted_proxy?("172.15.0.1").must_be_nil
|
1304
|
+
req.trusted_proxy?("172.32.0.1").must_be_nil
|
1305
|
+
req.trusted_proxy?("2001:470:1f0b:18f8::1").must_be_nil
|
1306
1306
|
end
|
1307
1307
|
|
1308
1308
|
it "sets the default session to an empty hash" do
|
data/test/spec_response.rb
CHANGED
@@ -55,7 +55,7 @@ describe Rack::Response do
|
|
55
55
|
|
56
56
|
it "can set and read headers" do
|
57
57
|
response = Rack::Response.new
|
58
|
-
response["Content-Type"].
|
58
|
+
response["Content-Type"].must_be_nil
|
59
59
|
response["Content-Type"] = "text/plain"
|
60
60
|
response["Content-Type"].must_equal "text/plain"
|
61
61
|
end
|
@@ -273,8 +273,8 @@ describe Rack::Response do
|
|
273
273
|
_, header, body = r.finish
|
274
274
|
str = ""; body.each { |part| str << part }
|
275
275
|
str.must_be :empty?
|
276
|
-
header["Content-Type"].
|
277
|
-
header['Content-Length'].
|
276
|
+
header["Content-Type"].must_be_nil
|
277
|
+
header['Content-Length'].must_be_nil
|
278
278
|
|
279
279
|
lambda {
|
280
280
|
Rack::Response.new(Object.new)
|
@@ -410,7 +410,7 @@ describe Rack::Response do
|
|
410
410
|
res.body.must_be :closed?
|
411
411
|
end
|
412
412
|
|
413
|
-
it "calls close on #body when 204
|
413
|
+
it "calls close on #body when 204 or 304" do
|
414
414
|
res = Rack::Response.new
|
415
415
|
res.body = StringIO.new
|
416
416
|
res.finish
|
@@ -424,7 +424,7 @@ describe Rack::Response do
|
|
424
424
|
res.body = StringIO.new
|
425
425
|
res.status = 205
|
426
426
|
_, _, b = res.finish
|
427
|
-
res.body.
|
427
|
+
res.body.wont_be :closed?
|
428
428
|
b.wont_equal res.body
|
429
429
|
|
430
430
|
res.body = StringIO.new
|
data/test/spec_server.rb
CHANGED
@@ -77,7 +77,7 @@ describe Rack::Server do
|
|
77
77
|
o, ENV["REQUEST_METHOD"] = ENV["REQUEST_METHOD"], 'foo'
|
78
78
|
server = Rack::Server.new(:app => 'foo')
|
79
79
|
server.server.name =~ /CGI/
|
80
|
-
Rack::Server.logging_middleware.call(server).
|
80
|
+
Rack::Server.logging_middleware.call(server).must_be_nil
|
81
81
|
ensure
|
82
82
|
ENV['REQUEST_METHOD'] = o
|
83
83
|
end
|
@@ -85,7 +85,7 @@ describe Rack::Server do
|
|
85
85
|
|
86
86
|
it "be quiet if said so" do
|
87
87
|
server = Rack::Server.new(:app => "FOO", :quiet => true)
|
88
|
-
Rack::Server.logging_middleware.call(server).
|
88
|
+
Rack::Server.logging_middleware.call(server).must_be_nil
|
89
89
|
end
|
90
90
|
|
91
91
|
it "use a full path to the pidfile" do
|
@@ -25,4 +25,21 @@ describe Rack::Session::Abstract::SessionHash do
|
|
25
25
|
assert_equal [:bar, :qux], hash.values
|
26
26
|
end
|
27
27
|
|
28
|
+
describe "#fetch" do
|
29
|
+
it "returns value for a matching key" do
|
30
|
+
assert_equal :bar, hash.fetch(:foo)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "works with a default value" do
|
34
|
+
assert_equal :default, hash.fetch(:unknown, :default)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "works with a block" do
|
38
|
+
assert_equal :default, hash.fetch(:unkown) { :default }
|
39
|
+
end
|
40
|
+
|
41
|
+
it "it raises when fetching unknown keys without defaults" do
|
42
|
+
lambda { hash.fetch(:unknown) }.must_raise KeyError
|
43
|
+
end
|
44
|
+
end
|
28
45
|
end
|
data/test/spec_session_cookie.rb
CHANGED
@@ -98,18 +98,18 @@ describe Rack::Session::Cookie do
|
|
98
98
|
|
99
99
|
it 'rescues failures on decode' do
|
100
100
|
coder = Rack::Session::Cookie::Base64::Marshal.new
|
101
|
-
coder.decode('lulz').
|
101
|
+
coder.decode('lulz').must_be_nil
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
105
|
describe 'JSON' do
|
106
|
-
it '
|
106
|
+
it 'JSON and base64 encodes' do
|
107
107
|
coder = Rack::Session::Cookie::Base64::JSON.new
|
108
108
|
obj = %w[fuuuuu]
|
109
109
|
coder.encode(obj).must_equal [::JSON.dump(obj)].pack('m')
|
110
110
|
end
|
111
111
|
|
112
|
-
it '
|
112
|
+
it 'JSON and base64 decodes' do
|
113
113
|
coder = Rack::Session::Cookie::Base64::JSON.new
|
114
114
|
str = [::JSON.dump(%w[fuuuuu])].pack('m')
|
115
115
|
coder.decode(str).must_equal ::JSON.parse(str.unpack('m').first)
|
@@ -117,7 +117,7 @@ describe Rack::Session::Cookie do
|
|
117
117
|
|
118
118
|
it 'rescues failures on decode' do
|
119
119
|
coder = Rack::Session::Cookie::Base64::JSON.new
|
120
|
-
coder.decode('lulz').
|
120
|
+
coder.decode('lulz').must_be_nil
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
@@ -139,7 +139,7 @@ describe Rack::Session::Cookie do
|
|
139
139
|
|
140
140
|
it 'rescues failures on decode' do
|
141
141
|
coder = Rack::Session::Cookie::Base64::ZipJSON.new
|
142
|
-
coder.decode('lulz').
|
142
|
+
coder.decode('lulz').must_be_nil
|
143
143
|
end
|
144
144
|
end
|
145
145
|
end
|
@@ -143,7 +143,7 @@ begin
|
|
143
143
|
res1.body.must_equal '{"counter"=>1}'
|
144
144
|
|
145
145
|
res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
|
146
|
-
res2["Set-Cookie"].
|
146
|
+
res2["Set-Cookie"].must_be_nil
|
147
147
|
res2.body.must_equal '{"counter"=>2}'
|
148
148
|
|
149
149
|
res3 = req.get("/", "HTTP_COOKIE" => cookie)
|
@@ -183,7 +183,7 @@ begin
|
|
183
183
|
creq = Rack::MockRequest.new(count)
|
184
184
|
|
185
185
|
res0 = dreq.get("/")
|
186
|
-
res0["Set-Cookie"].
|
186
|
+
res0["Set-Cookie"].must_be_nil
|
187
187
|
res0.body.must_equal '{"counter"=>1}'
|
188
188
|
|
189
189
|
res0 = creq.get("/")
|
@@ -201,7 +201,7 @@ begin
|
|
201
201
|
creq = Rack::MockRequest.new(count)
|
202
202
|
|
203
203
|
res0 = sreq.get("/")
|
204
|
-
res0["Set-Cookie"].
|
204
|
+
res0["Set-Cookie"].must_be_nil
|
205
205
|
res0.body.must_equal '{"counter"=>1}'
|
206
206
|
|
207
207
|
res0 = creq.get("/")
|
data/test/spec_session_pool.rb
CHANGED
@@ -138,7 +138,7 @@ describe Rack::Session::Pool do
|
|
138
138
|
dreq = Rack::MockRequest.new(defer)
|
139
139
|
|
140
140
|
res1 = dreq.get("/")
|
141
|
-
res1["Set-Cookie"].
|
141
|
+
res1["Set-Cookie"].must_be_nil
|
142
142
|
res1.body.must_equal '{"counter"=>1}'
|
143
143
|
pool.pool.size.must_equal 1
|
144
144
|
end
|
data/test/spec_static.rb
CHANGED
@@ -97,7 +97,7 @@ describe Rack::Static do
|
|
97
97
|
it "serves regular files if client accepts gzip encoding and gzip files are not present" do
|
98
98
|
res = @gzip_request.get("/cgi/rackup_stub.rb", 'HTTP_ACCEPT_ENCODING'=>'deflate, gzip')
|
99
99
|
res.must_be :ok?
|
100
|
-
res.headers['Content-Encoding'].
|
100
|
+
res.headers['Content-Encoding'].must_be_nil
|
101
101
|
res.headers['Content-Type'].must_equal 'text/x-script.ruby'
|
102
102
|
res.body.must_match(/ruby/)
|
103
103
|
end
|
@@ -105,7 +105,7 @@ describe Rack::Static do
|
|
105
105
|
it "serves regular files if client does not accept gzip encoding" do
|
106
106
|
res = @gzip_request.get("/cgi/test")
|
107
107
|
res.must_be :ok?
|
108
|
-
res.headers['Content-Encoding'].
|
108
|
+
res.headers['Content-Encoding'].must_be_nil
|
109
109
|
res.headers['Content-Type'].must_equal 'text/plain'
|
110
110
|
res.body.must_match(/ruby/)
|
111
111
|
end
|
data/test/spec_utils.rb
CHANGED
@@ -231,6 +231,18 @@ describe Rack::Utils do
|
|
231
231
|
message.must_equal "invalid byte sequence in UTF-8"
|
232
232
|
end
|
233
233
|
|
234
|
+
it "only moves to a new array when the full key has been seen" do
|
235
|
+
Rack::Utils.parse_nested_query("x[][y][][z]=1&x[][y][][w]=2").
|
236
|
+
must_equal "x" => [{"y" => [{"z" => "1", "w" => "2"}]}]
|
237
|
+
|
238
|
+
Rack::Utils.parse_nested_query(
|
239
|
+
"x[][id]=1&x[][y][a]=5&x[][y][b]=7&x[][z][id]=3&x[][z][w]=0&x[][id]=2&x[][y][a]=6&x[][y][b]=8&x[][z][id]=4&x[][z][w]=0"
|
240
|
+
).must_equal "x" => [
|
241
|
+
{"id" => "1", "y" => {"a" => "5", "b" => "7"}, "z" => {"id" => "3", "w" => "0"}},
|
242
|
+
{"id" => "2", "y" => {"a" => "6", "b" => "8"}, "z" => {"id" => "4", "w" => "0"}},
|
243
|
+
]
|
244
|
+
end
|
245
|
+
|
234
246
|
it "allow setting the params hash class to use for parsing query strings" do
|
235
247
|
begin
|
236
248
|
default_parser = Rack::Utils.default_query_parser
|
@@ -382,7 +394,7 @@ describe Rack::Utils do
|
|
382
394
|
Rack::Utils.best_q_match("text/plain,text/html", %w[text/html text/plain]).must_equal "text/html"
|
383
395
|
|
384
396
|
# When there are no matches, return nil:
|
385
|
-
Rack::Utils.best_q_match("application/json", %w[text/html text/plain]).
|
397
|
+
Rack::Utils.best_q_match("application/json", %w[text/html text/plain]).must_be_nil
|
386
398
|
end
|
387
399
|
|
388
400
|
it "escape html entities [&><'\"/]" do
|
@@ -415,9 +427,9 @@ describe Rack::Utils do
|
|
415
427
|
Rack::Utils.select_best_encoding(a, b)
|
416
428
|
end
|
417
429
|
|
418
|
-
helper.call(%w(), [["x", 1]]).
|
419
|
-
helper.call(%w(identity), [["identity", 0.0]]).
|
420
|
-
helper.call(%w(identity), [["*", 0.0]]).
|
430
|
+
helper.call(%w(), [["x", 1]]).must_be_nil
|
431
|
+
helper.call(%w(identity), [["identity", 0.0]]).must_be_nil
|
432
|
+
helper.call(%w(identity), [["*", 0.0]]).must_be_nil
|
421
433
|
|
422
434
|
helper.call(%w(identity), [["compress", 1.0], ["gzip", 1.0]]).must_equal "identity"
|
423
435
|
|
@@ -526,15 +538,15 @@ end
|
|
526
538
|
|
527
539
|
describe Rack::Utils, "byte_range" do
|
528
540
|
it "ignore missing or syntactically invalid byte ranges" do
|
529
|
-
Rack::Utils.byte_ranges({},500).
|
530
|
-
Rack::Utils.byte_ranges({"HTTP_RANGE" => "foobar"},500).
|
531
|
-
Rack::Utils.byte_ranges({"HTTP_RANGE" => "furlongs=123-456"},500).
|
532
|
-
Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes="},500).
|
533
|
-
Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-"},500).
|
534
|
-
Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123,456"},500).
|
541
|
+
Rack::Utils.byte_ranges({},500).must_be_nil
|
542
|
+
Rack::Utils.byte_ranges({"HTTP_RANGE" => "foobar"},500).must_be_nil
|
543
|
+
Rack::Utils.byte_ranges({"HTTP_RANGE" => "furlongs=123-456"},500).must_be_nil
|
544
|
+
Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes="},500).must_be_nil
|
545
|
+
Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-"},500).must_be_nil
|
546
|
+
Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123,456"},500).must_be_nil
|
535
547
|
# A range of non-positive length is syntactically invalid and ignored:
|
536
|
-
Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=456-123"},500).
|
537
|
-
Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=456-455"},500).
|
548
|
+
Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=456-123"},500).must_be_nil
|
549
|
+
Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=456-455"},500).must_be_nil
|
538
550
|
end
|
539
551
|
|
540
552
|
it "parse simple byte ranges" do
|
data/test/spec_webrick.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
2
|
require 'rack/mock'
|
3
|
+
require 'concurrent/utility/native_integer'
|
3
4
|
require 'concurrent/atomic/count_down_latch'
|
4
5
|
require File.expand_path('../testrequest', __FILE__)
|
5
6
|
|
@@ -171,7 +172,7 @@ describe Rack::Handler::WEBrick do
|
|
171
172
|
Rack::Lint.new(lambda{ |req|
|
172
173
|
[
|
173
174
|
200,
|
174
|
-
|
175
|
+
[ [ "rack.hijack", io_lambda ] ],
|
175
176
|
[""]
|
176
177
|
]
|
177
178
|
})
|
@@ -195,7 +196,7 @@ describe Rack::Handler::WEBrick do
|
|
195
196
|
Net::HTTP.start(@host, @port){ |http|
|
196
197
|
res = http.get("/chunked")
|
197
198
|
res["Transfer-Encoding"].must_equal "chunked"
|
198
|
-
res["Content-Length"].
|
199
|
+
res["Content-Length"].must_be_nil
|
199
200
|
res.body.must_equal "chunked"
|
200
201
|
}
|
201
202
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Neukirchen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: json
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: minitest
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -185,7 +171,6 @@ files:
|
|
185
171
|
- test/cgi/assets/javascripts/app.js
|
186
172
|
- test/cgi/assets/stylesheets/app.css
|
187
173
|
- test/cgi/lighttpd.conf
|
188
|
-
- test/cgi/lighttpd.errors
|
189
174
|
- test/cgi/rackup_stub.rb
|
190
175
|
- test/cgi/sample_rackup.ru
|
191
176
|
- test/cgi/test
|
@@ -206,6 +191,7 @@ files:
|
|
206
191
|
- test/multipart/filename_with_encoded_words
|
207
192
|
- test/multipart/filename_with_escaped_quotes
|
208
193
|
- test/multipart/filename_with_escaped_quotes_and_modification_param
|
194
|
+
- test/multipart/filename_with_null_byte
|
209
195
|
- test/multipart/filename_with_percent_escaped_quotes
|
210
196
|
- test/multipart/filename_with_single_quote
|
211
197
|
- test/multipart/filename_with_unescaped_percentages
|
@@ -298,12 +284,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
298
284
|
version: 2.2.2
|
299
285
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
300
286
|
requirements:
|
301
|
-
- - "
|
287
|
+
- - ">="
|
302
288
|
- !ruby/object:Gem::Version
|
303
|
-
version:
|
289
|
+
version: '0'
|
304
290
|
requirements: []
|
305
291
|
rubyforge_project:
|
306
|
-
rubygems_version: 2.6.
|
292
|
+
rubygems_version: 2.6.8
|
307
293
|
signing_key:
|
308
294
|
specification_version: 4
|
309
295
|
summary: a modular Ruby webserver interface
|
@@ -359,4 +345,3 @@ test_files:
|
|
359
345
|
- test/spec_utils.rb
|
360
346
|
- test/spec_version.rb
|
361
347
|
- test/spec_webrick.rb
|
362
|
-
has_rdoc:
|
data/test/cgi/lighttpd.errors
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
2016-05-04 12:00:25: (log.c.164) server started
|
2
|
-
2016-05-04 12:00:35: (server.c.1558) server stopped by UID = 502 PID = 80374
|
3
|
-
2016-05-04 12:13:42: (log.c.164) server started
|
4
|
-
2016-05-04 12:13:51: (server.c.1558) server stopped by UID = 502 PID = 82209
|
5
|
-
2016-05-04 12:16:30: (log.c.164) server started
|
6
|
-
2016-05-04 12:16:39: (server.c.1558) server stopped by UID = 502 PID = 82523
|
7
|
-
2016-05-04 12:18:17: (log.c.164) server started
|
8
|
-
2016-05-04 12:18:26: (server.c.1558) server stopped by UID = 502 PID = 82745
|