rack 1.6.13 → 2.2.3

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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +694 -0
  3. data/CONTRIBUTING.md +136 -0
  4. data/{COPYING → MIT-LICENSE} +4 -2
  5. data/README.rdoc +157 -163
  6. data/Rakefile +38 -32
  7. data/{SPEC → SPEC.rdoc} +41 -13
  8. data/bin/rackup +1 -0
  9. data/contrib/rack_logo.svg +164 -111
  10. data/example/lobster.ru +2 -0
  11. data/example/protectedlobster.rb +4 -2
  12. data/example/protectedlobster.ru +3 -1
  13. data/lib/rack/auth/abstract/handler.rb +3 -1
  14. data/lib/rack/auth/abstract/request.rb +6 -2
  15. data/lib/rack/auth/basic.rb +7 -4
  16. data/lib/rack/auth/digest/md5.rb +13 -11
  17. data/lib/rack/auth/digest/nonce.rb +6 -3
  18. data/lib/rack/auth/digest/params.rb +5 -4
  19. data/lib/rack/auth/digest/request.rb +6 -4
  20. data/lib/rack/body_proxy.rb +21 -15
  21. data/lib/rack/builder.rb +119 -26
  22. data/lib/rack/cascade.rb +28 -12
  23. data/lib/rack/chunked.rb +70 -22
  24. data/lib/rack/common_logger.rb +80 -0
  25. data/lib/rack/{conditionalget.rb → conditional_get.rb} +20 -16
  26. data/lib/rack/config.rb +2 -0
  27. data/lib/rack/content_length.rb +9 -8
  28. data/lib/rack/content_type.rb +5 -4
  29. data/lib/rack/core_ext/regexp.rb +14 -0
  30. data/lib/rack/deflater.rb +60 -70
  31. data/lib/rack/directory.rb +117 -85
  32. data/lib/rack/etag.rb +9 -7
  33. data/lib/rack/events.rb +153 -0
  34. data/lib/rack/file.rb +4 -149
  35. data/lib/rack/files.rb +218 -0
  36. data/lib/rack/handler/cgi.rb +17 -19
  37. data/lib/rack/handler/fastcgi.rb +17 -18
  38. data/lib/rack/handler/lsws.rb +14 -14
  39. data/lib/rack/handler/scgi.rb +22 -21
  40. data/lib/rack/handler/thin.rb +6 -3
  41. data/lib/rack/handler/webrick.rb +39 -32
  42. data/lib/rack/handler.rb +9 -26
  43. data/lib/rack/head.rb +16 -18
  44. data/lib/rack/lint.rb +110 -64
  45. data/lib/rack/lobster.rb +10 -10
  46. data/lib/rack/lock.rb +17 -11
  47. data/lib/rack/logger.rb +4 -2
  48. data/lib/rack/media_type.rb +43 -0
  49. data/lib/rack/{methodoverride.rb → method_override.rb} +10 -8
  50. data/lib/rack/mime.rb +27 -6
  51. data/lib/rack/mock.rb +124 -65
  52. data/lib/rack/multipart/generator.rb +20 -16
  53. data/lib/rack/multipart/parser.rb +273 -162
  54. data/lib/rack/multipart/uploaded_file.rb +15 -8
  55. data/lib/rack/multipart.rb +39 -8
  56. data/lib/rack/{nulllogger.rb → null_logger.rb} +3 -1
  57. data/lib/rack/query_parser.rb +217 -0
  58. data/lib/rack/recursive.rb +11 -9
  59. data/lib/rack/reloader.rb +8 -4
  60. data/lib/rack/request.rb +553 -305
  61. data/lib/rack/response.rb +244 -88
  62. data/lib/rack/rewindable_input.rb +5 -15
  63. data/lib/rack/runtime.rb +12 -18
  64. data/lib/rack/sendfile.rb +17 -15
  65. data/lib/rack/server.rb +125 -47
  66. data/lib/rack/session/abstract/id.rb +141 -93
  67. data/lib/rack/session/cookie.rb +35 -29
  68. data/lib/rack/session/memcache.rb +4 -93
  69. data/lib/rack/session/pool.rb +13 -11
  70. data/lib/rack/show_exceptions.rb +390 -0
  71. data/lib/rack/{showstatus.rb → show_status.rb} +12 -12
  72. data/lib/rack/static.rb +48 -11
  73. data/lib/rack/tempfile_reaper.rb +3 -3
  74. data/lib/rack/urlmap.rb +26 -19
  75. data/lib/rack/utils.rb +212 -294
  76. data/lib/rack/version.rb +29 -0
  77. data/lib/rack.rb +76 -33
  78. data/rack.gemspec +43 -30
  79. metadata +65 -187
  80. data/HISTORY.md +0 -375
  81. data/KNOWN-ISSUES +0 -44
  82. data/lib/rack/backports/uri/common_18.rb +0 -56
  83. data/lib/rack/backports/uri/common_192.rb +0 -52
  84. data/lib/rack/backports/uri/common_193.rb +0 -29
  85. data/lib/rack/commonlogger.rb +0 -72
  86. data/lib/rack/handler/evented_mongrel.rb +0 -8
  87. data/lib/rack/handler/mongrel.rb +0 -106
  88. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  89. data/lib/rack/showexceptions.rb +0 -387
  90. data/lib/rack/utils/okjson.rb +0 -600
  91. data/test/builder/anything.rb +0 -5
  92. data/test/builder/comment.ru +0 -4
  93. data/test/builder/end.ru +0 -5
  94. data/test/builder/line.ru +0 -1
  95. data/test/builder/options.ru +0 -2
  96. data/test/cgi/assets/folder/test.js +0 -1
  97. data/test/cgi/assets/fonts/font.eot +0 -1
  98. data/test/cgi/assets/images/image.png +0 -1
  99. data/test/cgi/assets/index.html +0 -1
  100. data/test/cgi/assets/javascripts/app.js +0 -1
  101. data/test/cgi/assets/stylesheets/app.css +0 -1
  102. data/test/cgi/lighttpd.conf +0 -26
  103. data/test/cgi/rackup_stub.rb +0 -6
  104. data/test/cgi/sample_rackup.ru +0 -5
  105. data/test/cgi/test +0 -9
  106. data/test/cgi/test+directory/test+file +0 -1
  107. data/test/cgi/test.fcgi +0 -8
  108. data/test/cgi/test.ru +0 -5
  109. data/test/gemloader.rb +0 -10
  110. data/test/multipart/bad_robots +0 -259
  111. data/test/multipart/binary +0 -0
  112. data/test/multipart/content_type_and_no_filename +0 -6
  113. data/test/multipart/empty +0 -10
  114. data/test/multipart/fail_16384_nofile +0 -814
  115. data/test/multipart/file1.txt +0 -1
  116. data/test/multipart/filename_and_modification_param +0 -7
  117. data/test/multipart/filename_and_no_name +0 -6
  118. data/test/multipart/filename_with_escaped_quotes +0 -6
  119. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  120. data/test/multipart/filename_with_null_byte +0 -7
  121. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  122. data/test/multipart/filename_with_unescaped_percentages +0 -6
  123. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  124. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  125. data/test/multipart/filename_with_unescaped_quotes +0 -6
  126. data/test/multipart/ie +0 -6
  127. data/test/multipart/invalid_character +0 -6
  128. data/test/multipart/mixed_files +0 -21
  129. data/test/multipart/nested +0 -10
  130. data/test/multipart/none +0 -9
  131. data/test/multipart/semicolon +0 -6
  132. data/test/multipart/text +0 -15
  133. data/test/multipart/three_files_three_fields +0 -31
  134. data/test/multipart/webkit +0 -32
  135. data/test/rackup/config.ru +0 -31
  136. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  137. data/test/spec_auth_basic.rb +0 -81
  138. data/test/spec_auth_digest.rb +0 -259
  139. data/test/spec_body_proxy.rb +0 -85
  140. data/test/spec_builder.rb +0 -223
  141. data/test/spec_cascade.rb +0 -61
  142. data/test/spec_cgi.rb +0 -102
  143. data/test/spec_chunked.rb +0 -101
  144. data/test/spec_commonlogger.rb +0 -93
  145. data/test/spec_conditionalget.rb +0 -102
  146. data/test/spec_config.rb +0 -22
  147. data/test/spec_content_length.rb +0 -85
  148. data/test/spec_content_type.rb +0 -45
  149. data/test/spec_deflater.rb +0 -339
  150. data/test/spec_directory.rb +0 -88
  151. data/test/spec_etag.rb +0 -107
  152. data/test/spec_fastcgi.rb +0 -107
  153. data/test/spec_file.rb +0 -221
  154. data/test/spec_handler.rb +0 -72
  155. data/test/spec_head.rb +0 -45
  156. data/test/spec_lint.rb +0 -550
  157. data/test/spec_lobster.rb +0 -58
  158. data/test/spec_lock.rb +0 -164
  159. data/test/spec_logger.rb +0 -23
  160. data/test/spec_methodoverride.rb +0 -111
  161. data/test/spec_mime.rb +0 -51
  162. data/test/spec_mock.rb +0 -297
  163. data/test/spec_mongrel.rb +0 -182
  164. data/test/spec_multipart.rb +0 -600
  165. data/test/spec_nulllogger.rb +0 -20
  166. data/test/spec_recursive.rb +0 -72
  167. data/test/spec_request.rb +0 -1232
  168. data/test/spec_response.rb +0 -407
  169. data/test/spec_rewindable_input.rb +0 -118
  170. data/test/spec_runtime.rb +0 -49
  171. data/test/spec_sendfile.rb +0 -130
  172. data/test/spec_server.rb +0 -167
  173. data/test/spec_session_abstract_id.rb +0 -53
  174. data/test/spec_session_cookie.rb +0 -410
  175. data/test/spec_session_memcache.rb +0 -358
  176. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  177. data/test/spec_session_pool.rb +0 -246
  178. data/test/spec_showexceptions.rb +0 -98
  179. data/test/spec_showstatus.rb +0 -103
  180. data/test/spec_static.rb +0 -145
  181. data/test/spec_tempfile_reaper.rb +0 -63
  182. data/test/spec_thin.rb +0 -91
  183. data/test/spec_urlmap.rb +0 -236
  184. data/test/spec_utils.rb +0 -647
  185. data/test/spec_version.rb +0 -17
  186. data/test/spec_webrick.rb +0 -184
  187. data/test/static/another/index.html +0 -1
  188. data/test/static/index.html +0 -1
  189. data/test/testrequest.rb +0 -78
  190. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  191. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -0,0 +1,217 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class QueryParser
5
+ (require_relative 'core_ext/regexp'; using ::Rack::RegexpExtensions) if RUBY_VERSION < '2.4'
6
+
7
+ DEFAULT_SEP = /[&;] */n
8
+ COMMON_SEP = { ";" => /[;] */n, ";," => /[;,] */n, "&" => /[&] */n }
9
+
10
+ # ParameterTypeError is the error that is raised when incoming structural
11
+ # parameters (parsed by parse_nested_query) contain conflicting types.
12
+ class ParameterTypeError < TypeError; end
13
+
14
+ # InvalidParameterError is the error that is raised when incoming structural
15
+ # parameters (parsed by parse_nested_query) contain invalid format or byte
16
+ # sequence.
17
+ class InvalidParameterError < ArgumentError; end
18
+
19
+ def self.make_default(key_space_limit, param_depth_limit)
20
+ new Params, key_space_limit, param_depth_limit
21
+ end
22
+
23
+ attr_reader :key_space_limit, :param_depth_limit
24
+
25
+ def initialize(params_class, key_space_limit, param_depth_limit)
26
+ @params_class = params_class
27
+ @key_space_limit = key_space_limit
28
+ @param_depth_limit = param_depth_limit
29
+ end
30
+
31
+ # Stolen from Mongrel, with some small modifications:
32
+ # Parses a query string by breaking it up at the '&'
33
+ # and ';' characters. You can also use this to parse
34
+ # cookies by changing the characters used in the second
35
+ # parameter (which defaults to '&;').
36
+ def parse_query(qs, d = nil, &unescaper)
37
+ unescaper ||= method(:unescape)
38
+
39
+ params = make_params
40
+
41
+ (qs || '').split(d ? (COMMON_SEP[d] || /[#{d}] */n) : DEFAULT_SEP).each do |p|
42
+ next if p.empty?
43
+ k, v = p.split('=', 2).map!(&unescaper)
44
+
45
+ if cur = params[k]
46
+ if cur.class == Array
47
+ params[k] << v
48
+ else
49
+ params[k] = [cur, v]
50
+ end
51
+ else
52
+ params[k] = v
53
+ end
54
+ end
55
+
56
+ return params.to_h
57
+ end
58
+
59
+ # parse_nested_query expands a query string into structural types. Supported
60
+ # types are Arrays, Hashes and basic value types. It is possible to supply
61
+ # query strings with parameters of conflicting types, in this case a
62
+ # ParameterTypeError is raised. Users are encouraged to return a 400 in this
63
+ # case.
64
+ def parse_nested_query(qs, d = nil)
65
+ params = make_params
66
+
67
+ unless qs.nil? || qs.empty?
68
+ (qs || '').split(d ? (COMMON_SEP[d] || /[#{d}] */n) : DEFAULT_SEP).each do |p|
69
+ k, v = p.split('=', 2).map! { |s| unescape(s) }
70
+
71
+ normalize_params(params, k, v, param_depth_limit)
72
+ end
73
+ end
74
+
75
+ return params.to_h
76
+ rescue ArgumentError => e
77
+ raise InvalidParameterError, e.message, e.backtrace
78
+ end
79
+
80
+ # normalize_params recursively expands parameters into structural types. If
81
+ # the structural types represented by two different parameter names are in
82
+ # conflict, a ParameterTypeError is raised.
83
+ def normalize_params(params, name, v, depth)
84
+ raise RangeError if depth <= 0
85
+
86
+ name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
87
+ k = $1 || ''
88
+ after = $' || ''
89
+
90
+ if k.empty?
91
+ if !v.nil? && name == "[]"
92
+ return Array(v)
93
+ else
94
+ return
95
+ end
96
+ end
97
+
98
+ if after == ''
99
+ params[k] = v
100
+ elsif after == "["
101
+ params[name] = v
102
+ elsif after == "[]"
103
+ params[k] ||= []
104
+ raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
105
+ params[k] << v
106
+ elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
107
+ child_key = $1
108
+ params[k] ||= []
109
+ raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
110
+ if params_hash_type?(params[k].last) && !params_hash_has_key?(params[k].last, child_key)
111
+ normalize_params(params[k].last, child_key, v, depth - 1)
112
+ else
113
+ params[k] << normalize_params(make_params, child_key, v, depth - 1)
114
+ end
115
+ else
116
+ params[k] ||= make_params
117
+ raise ParameterTypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params_hash_type?(params[k])
118
+ params[k] = normalize_params(params[k], after, v, depth - 1)
119
+ end
120
+
121
+ params
122
+ end
123
+
124
+ def make_params
125
+ @params_class.new @key_space_limit
126
+ end
127
+
128
+ def new_space_limit(key_space_limit)
129
+ self.class.new @params_class, key_space_limit, param_depth_limit
130
+ end
131
+
132
+ def new_depth_limit(param_depth_limit)
133
+ self.class.new @params_class, key_space_limit, param_depth_limit
134
+ end
135
+
136
+ private
137
+
138
+ def params_hash_type?(obj)
139
+ obj.kind_of?(@params_class)
140
+ end
141
+
142
+ def params_hash_has_key?(hash, key)
143
+ return false if /\[\]/.match?(key)
144
+
145
+ key.split(/[\[\]]+/).inject(hash) do |h, part|
146
+ next h if part == ''
147
+ return false unless params_hash_type?(h) && h.key?(part)
148
+ h[part]
149
+ end
150
+
151
+ true
152
+ end
153
+
154
+ def unescape(s)
155
+ Utils.unescape(s)
156
+ end
157
+
158
+ class Params
159
+ def initialize(limit)
160
+ @limit = limit
161
+ @size = 0
162
+ @params = {}
163
+ end
164
+
165
+ def [](key)
166
+ @params[key]
167
+ end
168
+
169
+ def []=(key, value)
170
+ @size += key.size if key && !@params.key?(key)
171
+ raise RangeError, 'exceeded available parameter key space' if @size > @limit
172
+ @params[key] = value
173
+ end
174
+
175
+ def key?(key)
176
+ @params.key?(key)
177
+ end
178
+
179
+ # Recursively unwraps nested `Params` objects and constructs an object
180
+ # of the same shape, but using the objects' internal representations
181
+ # (Ruby hashes) in place of the objects. The result is a hash consisting
182
+ # purely of Ruby primitives.
183
+ #
184
+ # Mutation warning!
185
+ #
186
+ # 1. This method mutates the internal representation of the `Params`
187
+ # objects in order to save object allocations.
188
+ #
189
+ # 2. The value you get back is a reference to the internal hash
190
+ # representation, not a copy.
191
+ #
192
+ # 3. Because the `Params` object's internal representation is mutable
193
+ # through the `#[]=` method, it is not thread safe. The result of
194
+ # getting the hash representation while another thread is adding a
195
+ # key to it is non-deterministic.
196
+ #
197
+ def to_h
198
+ @params.each do |key, value|
199
+ case value
200
+ when self
201
+ # Handle circular references gracefully.
202
+ @params[key] = @params
203
+ when Params
204
+ @params[key] = value.to_h
205
+ when Array
206
+ value.map! { |v| v.kind_of?(Params) ? v.to_h : v }
207
+ else
208
+ # Ignore anything that is not a `Params` object or
209
+ # a collection that can contain one.
210
+ end
211
+ end
212
+ @params
213
+ end
214
+ alias_method :to_params_hash, :to_h
215
+ end
216
+ end
217
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
 
3
5
  module Rack
@@ -10,15 +12,15 @@ module Rack
10
12
  class ForwardRequest < Exception
11
13
  attr_reader :url, :env
12
14
 
13
- def initialize(url, env={})
15
+ def initialize(url, env = {})
14
16
  @url = URI(url)
15
17
  @env = env
16
18
 
17
- @env[PATH_INFO] = @url.path
18
- @env[QUERY_STRING] = @url.query if @url.query
19
- @env["HTTP_HOST"] = @url.host if @url.host
20
- @env["HTTP_PORT"] = @url.port if @url.port
21
- @env["rack.url_scheme"] = @url.scheme if @url.scheme
19
+ @env[PATH_INFO] = @url.path
20
+ @env[QUERY_STRING] = @url.query if @url.query
21
+ @env[HTTP_HOST] = @url.host if @url.host
22
+ @env[HTTP_PORT] = @url.port if @url.port
23
+ @env[RACK_URL_SCHEME] = @url.scheme if @url.scheme
22
24
 
23
25
  super "forwarding to #{url}"
24
26
  end
@@ -40,7 +42,7 @@ module Rack
40
42
 
41
43
  def _call(env)
42
44
  @script_name = env[SCRIPT_NAME]
43
- @app.call(env.merge('rack.recursive.include' => method(:include)))
45
+ @app.call(env.merge(RACK_RECURSIVE_INCLUDE => method(:include)))
44
46
  rescue ForwardRequest => req
45
47
  call(env.merge(req.env))
46
48
  end
@@ -53,9 +55,9 @@ module Rack
53
55
 
54
56
  env = env.merge(PATH_INFO => path,
55
57
  SCRIPT_NAME => @script_name,
56
- REQUEST_METHOD => "GET",
58
+ REQUEST_METHOD => GET,
57
59
  "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "",
58
- "rack.input" => StringIO.new(""))
60
+ RACK_INPUT => StringIO.new(""))
59
61
  @app.call(env)
60
62
  end
61
63
  end
data/lib/rack/reloader.rb CHANGED
@@ -1,6 +1,8 @@
1
- # Copyright (c) 2009 Michael Fellinger m.fellinger@gmail.com
2
- # Rack::Reloader is subject to the terms of an MIT-style license.
3
- # See COPYING or http://www.opensource.org/licenses/mit-license.php.
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (C) 2009-2018 Michael Fellinger <m.fellinger@gmail.com>
4
+ # Rack::Reloader is subject to the terms of an MIT-style license.
5
+ # See MIT-LICENSE or https://opensource.org/licenses/MIT.
4
6
 
5
7
  require 'pathname'
6
8
 
@@ -20,6 +22,8 @@ module Rack
20
22
  # It is performing a check/reload cycle at the start of every request, but
21
23
  # also respects a cool down time, during which nothing will be done.
22
24
  class Reloader
25
+ (require_relative 'core_ext/regexp'; using ::Rack::RegexpExtensions) if RUBY_VERSION < '2.4'
26
+
23
27
  def initialize(app, cooldown = 10, backend = Stat)
24
28
  @app = app
25
29
  @cooldown = cooldown
@@ -69,7 +73,7 @@ module Rack
69
73
  paths = ['./', *$LOAD_PATH].uniq
70
74
 
71
75
  files.map{|file|
72
- next if file =~ /\.(so|bundle)$/ # cannot reload compiled files
76
+ next if /\.(so|bundle)$/.match?(file) # cannot reload compiled files
73
77
 
74
78
  found, stat = figure_path(file, paths)
75
79
  next unless found && stat && mtime = stat.mtime