rack 2.2.17 → 3.0.18

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.

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