rack 2.2.4 → 3.0.8

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.

Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +223 -71
  3. data/CONTRIBUTING.md +53 -47
  4. data/MIT-LICENSE +1 -1
  5. data/README.md +309 -0
  6. data/SPEC.rdoc +183 -131
  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 +0 -2
  10. data/lib/rack/auth/digest/md5.rb +1 -131
  11. data/lib/rack/auth/digest/nonce.rb +1 -54
  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 +3 -1
  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 +23 -18
  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 +14 -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 +783 -682
  33. data/lib/rack/lock.rb +2 -5
  34. data/lib/rack/logger.rb +2 -0
  35. data/lib/rack/media_type.rb +1 -1
  36. data/lib/rack/method_override.rb +6 -2
  37. data/lib/rack/mime.rb +8 -0
  38. data/lib/rack/mock.rb +1 -271
  39. data/lib/rack/mock_request.rb +166 -0
  40. data/lib/rack/mock_response.rb +126 -0
  41. data/lib/rack/multipart/generator.rb +7 -5
  42. data/lib/rack/multipart/parser.rb +134 -65
  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 +226 -108
  50. data/lib/rack/response.rb +136 -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 +4 -2
  59. data/lib/rack/utils.rb +223 -185
  60. data/lib/rack/version.rb +9 -4
  61. data/lib/rack.rb +6 -76
  62. metadata +18 -38
  63. data/README.rdoc +0 -306
  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 -85
  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
@@ -20,29 +20,35 @@ module Rack
20
20
  # nested over the specified limit.
21
21
  class ParamsTooDeepError < RangeError; end
22
22
 
23
- def self.make_default(key_space_limit, param_depth_limit)
24
- new Params, key_space_limit, param_depth_limit
23
+ def self.make_default(_key_space_limit=(not_deprecated = true; nil), param_depth_limit)
24
+ unless not_deprecated
25
+ 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)
26
+ end
27
+
28
+ new Params, param_depth_limit
25
29
  end
26
30
 
27
- attr_reader :key_space_limit, :param_depth_limit
31
+ attr_reader :param_depth_limit
32
+
33
+ def initialize(params_class, _key_space_limit=(not_deprecated = true; nil), param_depth_limit)
34
+ unless not_deprecated
35
+ 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)
36
+ end
28
37
 
29
- def initialize(params_class, key_space_limit, param_depth_limit)
30
38
  @params_class = params_class
31
- @key_space_limit = key_space_limit
32
39
  @param_depth_limit = param_depth_limit
33
40
  end
34
41
 
35
42
  # Stolen from Mongrel, with some small modifications:
36
- # Parses a query string by breaking it up at the '&'
37
- # and ';' characters. You can also use this to parse
38
- # cookies by changing the characters used in the second
39
- # parameter (which defaults to '&;').
40
- def parse_query(qs, d = nil, &unescaper)
43
+ # Parses a query string by breaking it up at the '&'. You can also use this
44
+ # to parse cookies by changing the characters used in the second parameter
45
+ # (which defaults to '&').
46
+ def parse_query(qs, separator = nil, &unescaper)
41
47
  unescaper ||= method(:unescape)
42
48
 
43
49
  params = make_params
44
50
 
45
- (qs || '').split(d ? (COMMON_SEP[d] || /[#{d}] */n) : DEFAULT_SEP).each do |p|
51
+ (qs || '').split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
46
52
  next if p.empty?
47
53
  k, v = p.split('=', 2).map!(&unescaper)
48
54
 
@@ -65,14 +71,14 @@ module Rack
65
71
  # query strings with parameters of conflicting types, in this case a
66
72
  # ParameterTypeError is raised. Users are encouraged to return a 400 in this
67
73
  # case.
68
- def parse_nested_query(qs, d = nil)
74
+ def parse_nested_query(qs, separator = nil)
69
75
  params = make_params
70
76
 
71
77
  unless qs.nil? || qs.empty?
72
- (qs || '').split(d ? (COMMON_SEP[d] || /[#{d}] */n) : DEFAULT_SEP).each do |p|
78
+ (qs || '').split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
73
79
  k, v = p.split('=', 2).map! { |s| unescape(s) }
74
80
 
75
- normalize_params(params, k, v, param_depth_limit)
81
+ _normalize_params(params, k, v, 0)
76
82
  end
77
83
  end
78
84
 
@@ -83,58 +89,87 @@ module Rack
83
89
 
84
90
  # normalize_params recursively expands parameters into structural types. If
85
91
  # the structural types represented by two different parameter names are in
86
- # conflict, a ParameterTypeError is raised.
87
- def normalize_params(params, name, v, depth)
88
- raise ParamsTooDeepError if depth <= 0
89
-
90
- name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
91
- k = $1 || ''
92
- after = $' || ''
92
+ # conflict, a ParameterTypeError is raised. The depth argument is deprecated
93
+ # and should no longer be used, it is kept for backwards compatibility with
94
+ # earlier versions of rack.
95
+ def normalize_params(params, name, v, _depth=nil)
96
+ _normalize_params(params, name, v, 0)
97
+ end
93
98
 
94
- if k.empty?
95
- if !v.nil? && name == "[]"
96
- return Array(v)
99
+ private def _normalize_params(params, name, v, depth)
100
+ raise ParamsTooDeepError if depth >= param_depth_limit
101
+
102
+ if !name
103
+ # nil name, treat same as empty string (required by tests)
104
+ k = after = ''
105
+ elsif depth == 0
106
+ # Start of parsing, don't treat [] or [ at start of string specially
107
+ if start = name.index('[', 1)
108
+ # Start of parameter nesting, use part before brackets as key
109
+ k = name[0, start]
110
+ after = name[start, name.length]
97
111
  else
98
- return
112
+ # Plain parameter with no nesting
113
+ k = name
114
+ after = ''
99
115
  end
116
+ elsif name.start_with?('[]')
117
+ # Array nesting
118
+ k = '[]'
119
+ after = name[2, name.length]
120
+ elsif name.start_with?('[') && (start = name.index(']', 1))
121
+ # Hash nesting, use the part inside brackets as the key
122
+ k = name[1, start-1]
123
+ after = name[start+1, name.length]
124
+ else
125
+ # Probably malformed input, nested but not starting with [
126
+ # treat full name as key for backwards compatibility.
127
+ k = name
128
+ after = ''
100
129
  end
101
130
 
131
+ return if k.empty?
132
+
102
133
  if after == ''
103
- params[k] = v
134
+ if k == '[]' && depth != 0
135
+ return [v]
136
+ else
137
+ params[k] = v
138
+ end
104
139
  elsif after == "["
105
140
  params[name] = v
106
141
  elsif after == "[]"
107
142
  params[k] ||= []
108
143
  raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
109
144
  params[k] << v
110
- elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
111
- child_key = $1
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
112
151
  params[k] ||= []
113
152
  raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
114
153
  if params_hash_type?(params[k].last) && !params_hash_has_key?(params[k].last, child_key)
115
- normalize_params(params[k].last, child_key, v, depth - 1)
154
+ _normalize_params(params[k].last, child_key, v, depth + 1)
116
155
  else
117
- params[k] << normalize_params(make_params, child_key, v, depth - 1)
156
+ params[k] << _normalize_params(make_params, child_key, v, depth + 1)
118
157
  end
119
158
  else
120
159
  params[k] ||= make_params
121
160
  raise ParameterTypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params_hash_type?(params[k])
122
- params[k] = normalize_params(params[k], after, v, depth - 1)
161
+ params[k] = _normalize_params(params[k], after, v, depth + 1)
123
162
  end
124
163
 
125
164
  params
126
165
  end
127
166
 
128
167
  def make_params
129
- @params_class.new @key_space_limit
130
- end
131
-
132
- def new_space_limit(key_space_limit)
133
- self.class.new @params_class, key_space_limit, param_depth_limit
168
+ @params_class.new
134
169
  end
135
170
 
136
171
  def new_depth_limit(param_depth_limit)
137
- self.class.new @params_class, key_space_limit, param_depth_limit
172
+ self.class.new @params_class, param_depth_limit
138
173
  end
139
174
 
140
175
  private
@@ -155,13 +190,12 @@ module Rack
155
190
  true
156
191
  end
157
192
 
158
- def unescape(s)
159
- Utils.unescape(s)
193
+ def unescape(string, encoding = Encoding::UTF_8)
194
+ URI.decode_www_form_component(string, encoding)
160
195
  end
161
196
 
162
197
  class Params
163
- def initialize(limit)
164
- @limit = limit
198
+ def initialize
165
199
  @size = 0
166
200
  @params = {}
167
201
  end
@@ -171,8 +205,6 @@ module Rack
171
205
  end
172
206
 
173
207
  def []=(key, value)
174
- @size += key.size if key && !@params.key?(key)
175
- raise ParamsTooDeepError, 'exceeded available parameter key space' if @size > @limit
176
208
  @params[key] = value
177
209
  end
178
210
 
@@ -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