rack 2.2.14 → 3.0.3
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.
Potentially problematic release.
This version of rack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +163 -114
- data/CONTRIBUTING.md +53 -47
- data/MIT-LICENSE +1 -1
- data/README.md +293 -0
- data/SPEC.rdoc +174 -126
- data/lib/rack/auth/abstract/handler.rb +3 -1
- data/lib/rack/auth/abstract/request.rb +3 -1
- data/lib/rack/auth/basic.rb +2 -3
- data/lib/rack/auth/digest/md5.rb +1 -131
- data/lib/rack/auth/digest/nonce.rb +1 -53
- data/lib/rack/auth/digest/params.rb +1 -54
- data/lib/rack/auth/digest/request.rb +1 -43
- data/lib/rack/auth/digest.rb +256 -0
- data/lib/rack/body_proxy.rb +3 -1
- data/lib/rack/builder.rb +83 -63
- data/lib/rack/cascade.rb +2 -0
- data/lib/rack/chunked.rb +16 -13
- data/lib/rack/common_logger.rb +24 -20
- data/lib/rack/conditional_get.rb +18 -15
- data/lib/rack/constants.rb +63 -0
- data/lib/rack/content_length.rb +12 -16
- data/lib/rack/content_type.rb +8 -5
- data/lib/rack/deflater.rb +40 -26
- data/lib/rack/directory.rb +9 -3
- data/lib/rack/etag.rb +14 -23
- data/lib/rack/events.rb +4 -0
- data/lib/rack/file.rb +2 -0
- data/lib/rack/files.rb +15 -17
- data/lib/rack/head.rb +9 -8
- data/lib/rack/headers.rb +154 -0
- data/lib/rack/lint.rb +758 -646
- data/lib/rack/lock.rb +2 -5
- data/lib/rack/logger.rb +2 -0
- data/lib/rack/media_type.rb +4 -9
- data/lib/rack/method_override.rb +6 -2
- data/lib/rack/mime.rb +8 -0
- data/lib/rack/mock.rb +1 -271
- data/lib/rack/mock_request.rb +166 -0
- data/lib/rack/mock_response.rb +126 -0
- data/lib/rack/multipart/generator.rb +7 -5
- data/lib/rack/multipart/parser.rb +123 -85
- data/lib/rack/multipart/uploaded_file.rb +4 -0
- data/lib/rack/multipart.rb +20 -40
- data/lib/rack/null_logger.rb +9 -0
- data/lib/rack/query_parser.rb +78 -89
- data/lib/rack/recursive.rb +2 -0
- data/lib/rack/reloader.rb +0 -2
- data/lib/rack/request.rb +189 -91
- data/lib/rack/response.rb +136 -61
- data/lib/rack/rewindable_input.rb +24 -5
- data/lib/rack/runtime.rb +7 -6
- data/lib/rack/sendfile.rb +31 -26
- data/lib/rack/show_exceptions.rb +15 -2
- data/lib/rack/show_status.rb +17 -7
- data/lib/rack/static.rb +9 -10
- data/lib/rack/tempfile_reaper.rb +15 -4
- data/lib/rack/urlmap.rb +3 -1
- data/lib/rack/utils.rb +215 -205
- data/lib/rack/version.rb +9 -4
- data/lib/rack.rb +5 -76
- metadata +15 -35
- data/README.rdoc +0 -347
- data/Rakefile +0 -130
- data/bin/rackup +0 -5
- data/contrib/rack.png +0 -0
- data/contrib/rack.svg +0 -150
- data/contrib/rack_logo.svg +0 -164
- data/contrib/rdoc.css +0 -412
- data/example/lobster.ru +0 -6
- data/example/protectedlobster.rb +0 -16
- data/example/protectedlobster.ru +0 -10
- data/lib/rack/core_ext/regexp.rb +0 -14
- data/lib/rack/handler/cgi.rb +0 -59
- data/lib/rack/handler/fastcgi.rb +0 -100
- data/lib/rack/handler/lsws.rb +0 -61
- data/lib/rack/handler/scgi.rb +0 -71
- data/lib/rack/handler/thin.rb +0 -36
- data/lib/rack/handler/webrick.rb +0 -129
- data/lib/rack/handler.rb +0 -104
- data/lib/rack/lobster.rb +0 -70
- data/lib/rack/server.rb +0 -466
- data/lib/rack/session/abstract/id.rb +0 -523
- data/lib/rack/session/cookie.rb +0 -203
- data/lib/rack/session/memcache.rb +0 -10
- data/lib/rack/session/pool.rb +0 -90
- data/rack.gemspec +0 -46
data/lib/rack/query_parser.rb
CHANGED
@@ -2,9 +2,7 @@
|
|
2
2
|
|
3
3
|
module Rack
|
4
4
|
class QueryParser
|
5
|
-
|
6
|
-
|
7
|
-
DEFAULT_SEP = /[&;] */n
|
5
|
+
DEFAULT_SEP = /[&] */n
|
8
6
|
COMMON_SEP = { ";" => /[;] */n, ";," => /[;,] */n, "&" => /[&] */n }
|
9
7
|
|
10
8
|
# ParameterTypeError is the error that is raised when incoming structural
|
@@ -16,60 +14,39 @@ module Rack
|
|
16
14
|
# sequence.
|
17
15
|
class InvalidParameterError < ArgumentError; end
|
18
16
|
|
19
|
-
#
|
20
|
-
#
|
21
|
-
class
|
22
|
-
end
|
23
|
-
|
24
|
-
# ParamsTooDeepError is the old name for the error that is raised when params
|
25
|
-
# are recursively nested over the specified limit. Make it the same as
|
26
|
-
# as QueryLimitError, so that code that rescues ParamsTooDeepError error
|
27
|
-
# to handle bad query strings also now handles other limits.
|
28
|
-
ParamsTooDeepError = QueryLimitError
|
17
|
+
# ParamsTooDeepError is the error that is raised when params are recursively
|
18
|
+
# nested over the specified limit.
|
19
|
+
class ParamsTooDeepError < RangeError; end
|
29
20
|
|
30
|
-
def self.make_default(
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
attr_reader :key_space_limit, :param_depth_limit
|
35
|
-
|
36
|
-
env_int = lambda do |key, val|
|
37
|
-
if str_val = ENV[key]
|
38
|
-
begin
|
39
|
-
val = Integer(str_val, 10)
|
40
|
-
rescue ArgumentError
|
41
|
-
raise ArgumentError, "non-integer value provided for environment variable #{key}"
|
42
|
-
end
|
21
|
+
def self.make_default(_key_space_limit=(not_deprecated = true; nil), param_depth_limit)
|
22
|
+
unless not_deprecated
|
23
|
+
warn("`first argument `key_space limit` is deprecated and no longer has an effect. Please call with only one argument, which will be required in a future version of Rack", uplevel: 1)
|
43
24
|
end
|
44
25
|
|
45
|
-
|
26
|
+
new Params, param_depth_limit
|
46
27
|
end
|
47
28
|
|
48
|
-
|
49
|
-
private_constant :BYTESIZE_LIMIT
|
29
|
+
attr_reader :param_depth_limit
|
50
30
|
|
51
|
-
|
52
|
-
|
31
|
+
def initialize(params_class, _key_space_limit=(not_deprecated = true; nil), param_depth_limit)
|
32
|
+
unless not_deprecated
|
33
|
+
warn("`second argument `key_space limit` is deprecated and no longer has an effect. Please call with only two arguments, which will be required in a future version of Rack", uplevel: 1)
|
34
|
+
end
|
53
35
|
|
54
|
-
def initialize(params_class, key_space_limit, param_depth_limit, bytesize_limit: BYTESIZE_LIMIT, params_limit: PARAMS_LIMIT)
|
55
36
|
@params_class = params_class
|
56
|
-
@key_space_limit = key_space_limit
|
57
37
|
@param_depth_limit = param_depth_limit
|
58
|
-
@bytesize_limit = bytesize_limit
|
59
|
-
@params_limit = params_limit
|
60
38
|
end
|
61
39
|
|
62
40
|
# Stolen from Mongrel, with some small modifications:
|
63
|
-
# Parses a query string by breaking it up at the '&'
|
64
|
-
#
|
65
|
-
#
|
66
|
-
|
67
|
-
def parse_query(qs, d = nil, &unescaper)
|
41
|
+
# Parses a query string by breaking it up at the '&'. You can also use this
|
42
|
+
# to parse cookies by changing the characters used in the second parameter
|
43
|
+
# (which defaults to '&').
|
44
|
+
def parse_query(qs, separator = nil, &unescaper)
|
68
45
|
unescaper ||= method(:unescape)
|
69
46
|
|
70
47
|
params = make_params
|
71
48
|
|
72
|
-
|
49
|
+
(qs || '').split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
|
73
50
|
next if p.empty?
|
74
51
|
k, v = p.split('=', 2).map!(&unescaper)
|
75
52
|
|
@@ -92,14 +69,14 @@ module Rack
|
|
92
69
|
# query strings with parameters of conflicting types, in this case a
|
93
70
|
# ParameterTypeError is raised. Users are encouraged to return a 400 in this
|
94
71
|
# case.
|
95
|
-
def parse_nested_query(qs,
|
72
|
+
def parse_nested_query(qs, separator = nil)
|
96
73
|
params = make_params
|
97
74
|
|
98
75
|
unless qs.nil? || qs.empty?
|
99
|
-
|
76
|
+
(qs || '').split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
|
100
77
|
k, v = p.split('=', 2).map! { |s| unescape(s) }
|
101
78
|
|
102
|
-
|
79
|
+
_normalize_params(params, k, v, 0)
|
103
80
|
end
|
104
81
|
end
|
105
82
|
|
@@ -110,58 +87,89 @@ module Rack
|
|
110
87
|
|
111
88
|
# normalize_params recursively expands parameters into structural types. If
|
112
89
|
# the structural types represented by two different parameter names are in
|
113
|
-
# conflict, a ParameterTypeError is raised.
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
name
|
118
|
-
|
119
|
-
after = $' || ''
|
90
|
+
# conflict, a ParameterTypeError is raised. The depth argument is deprecated
|
91
|
+
# and should no longer be used, it is kept for backwards compatibility with
|
92
|
+
# earlier versions of rack.
|
93
|
+
def normalize_params(params, name, v, _depth=nil)
|
94
|
+
_normalize_params(params, name, v, 0)
|
95
|
+
end
|
120
96
|
|
121
|
-
|
122
|
-
|
123
|
-
|
97
|
+
private def _normalize_params(params, name, v, depth)
|
98
|
+
raise ParamsTooDeepError if depth >= param_depth_limit
|
99
|
+
|
100
|
+
if !name
|
101
|
+
# nil name, treat same as empty string (required by tests)
|
102
|
+
k = after = ''
|
103
|
+
elsif depth == 0
|
104
|
+
# Start of parsing, don't treat [] or [ at start of string specially
|
105
|
+
if start = name.index('[', 1)
|
106
|
+
# Start of parameter nesting, use part before brackets as key
|
107
|
+
k = name[0, start]
|
108
|
+
after = name[start, name.length]
|
124
109
|
else
|
125
|
-
|
110
|
+
# Plain parameter with no nesting
|
111
|
+
k = name
|
112
|
+
after = ''
|
126
113
|
end
|
114
|
+
elsif name.start_with?('[]')
|
115
|
+
# Array nesting
|
116
|
+
k = '[]'
|
117
|
+
after = name[2, name.length]
|
118
|
+
elsif name.start_with?('[') && (start = name.index(']', 1))
|
119
|
+
# Hash nesting, use the part inside brackets as the key
|
120
|
+
k = name[1, start-1]
|
121
|
+
after = name[start+1, name.length]
|
122
|
+
else
|
123
|
+
# Probably malformed input, nested but not starting with [
|
124
|
+
# treat full name as key for backwards compatibility.
|
125
|
+
k = name
|
126
|
+
after = ''
|
127
127
|
end
|
128
128
|
|
129
|
+
return if k.empty?
|
130
|
+
|
131
|
+
v ||= String.new
|
132
|
+
|
129
133
|
if after == ''
|
130
|
-
|
134
|
+
if k == '[]' && depth != 0
|
135
|
+
return [v]
|
136
|
+
else
|
137
|
+
params[k] = v
|
138
|
+
end
|
131
139
|
elsif after == "["
|
132
140
|
params[name] = v
|
133
141
|
elsif after == "[]"
|
134
142
|
params[k] ||= []
|
135
143
|
raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
|
136
144
|
params[k] << v
|
137
|
-
elsif after
|
138
|
-
|
145
|
+
elsif after.start_with?('[]')
|
146
|
+
# Recognize x[][y] (hash inside array) parameters
|
147
|
+
unless after[2] == '[' && after.end_with?(']') && (child_key = after[3, after.length-4]) && !child_key.empty? && !child_key.index('[') && !child_key.index(']')
|
148
|
+
# Handle other nested array parameters
|
149
|
+
child_key = after[2, after.length]
|
150
|
+
end
|
139
151
|
params[k] ||= []
|
140
152
|
raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
|
141
153
|
if params_hash_type?(params[k].last) && !params_hash_has_key?(params[k].last, child_key)
|
142
|
-
|
154
|
+
_normalize_params(params[k].last, child_key, v, depth + 1)
|
143
155
|
else
|
144
|
-
params[k] <<
|
156
|
+
params[k] << _normalize_params(make_params, child_key, v, depth + 1)
|
145
157
|
end
|
146
158
|
else
|
147
159
|
params[k] ||= make_params
|
148
160
|
raise ParameterTypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params_hash_type?(params[k])
|
149
|
-
params[k] =
|
161
|
+
params[k] = _normalize_params(params[k], after, v, depth + 1)
|
150
162
|
end
|
151
163
|
|
152
164
|
params
|
153
165
|
end
|
154
166
|
|
155
167
|
def make_params
|
156
|
-
@params_class.new
|
157
|
-
end
|
158
|
-
|
159
|
-
def new_space_limit(key_space_limit)
|
160
|
-
self.class.new @params_class, key_space_limit, param_depth_limit
|
168
|
+
@params_class.new
|
161
169
|
end
|
162
170
|
|
163
171
|
def new_depth_limit(param_depth_limit)
|
164
|
-
self.class.new @params_class,
|
172
|
+
self.class.new @params_class, param_depth_limit
|
165
173
|
end
|
166
174
|
|
167
175
|
private
|
@@ -182,29 +190,12 @@ module Rack
|
|
182
190
|
true
|
183
191
|
end
|
184
192
|
|
185
|
-
def
|
186
|
-
|
187
|
-
if qs.bytesize > @bytesize_limit
|
188
|
-
raise QueryLimitError, "total query size (#{qs.bytesize}) exceeds limit (#{@bytesize_limit})"
|
189
|
-
end
|
190
|
-
|
191
|
-
if (param_count = qs.count(sep.is_a?(String) ? sep : '&')) >= @params_limit
|
192
|
-
raise QueryLimitError, "total number of query parameters (#{param_count+1}) exceeds limit (#{@params_limit})"
|
193
|
-
end
|
194
|
-
|
195
|
-
qs
|
196
|
-
else
|
197
|
-
''
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
def unescape(string)
|
202
|
-
Utils.unescape(string)
|
193
|
+
def unescape(s)
|
194
|
+
Utils.unescape(s)
|
203
195
|
end
|
204
196
|
|
205
197
|
class Params
|
206
|
-
def initialize
|
207
|
-
@limit = limit
|
198
|
+
def initialize
|
208
199
|
@size = 0
|
209
200
|
@params = {}
|
210
201
|
end
|
@@ -214,8 +205,6 @@ module Rack
|
|
214
205
|
end
|
215
206
|
|
216
207
|
def []=(key, value)
|
217
|
-
@size += key.size if key && !@params.key?(key)
|
218
|
-
raise ParamsTooDeepError, 'exceeded available parameter key space' if @size > @limit
|
219
208
|
@params[key] = value
|
220
209
|
end
|
221
210
|
|
data/lib/rack/recursive.rb
CHANGED
data/lib/rack/reloader.rb
CHANGED
@@ -22,8 +22,6 @@ module Rack
|
|
22
22
|
# It is performing a check/reload cycle at the start of every request, but
|
23
23
|
# also respects a cool down time, during which nothing will be done.
|
24
24
|
class Reloader
|
25
|
-
(require_relative 'core_ext/regexp'; using ::Rack::RegexpExtensions) if RUBY_VERSION < '2.4'
|
26
|
-
|
27
25
|
def initialize(app, cooldown = 10, backend = Stat)
|
28
26
|
@app = app
|
29
27
|
@cooldown = cooldown
|