rack 2.1.0 → 3.1.0

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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +377 -16
  3. data/CONTRIBUTING.md +144 -0
  4. data/MIT-LICENSE +1 -1
  5. data/README.md +328 -0
  6. data/SPEC.rdoc +365 -0
  7. data/lib/rack/auth/abstract/handler.rb +3 -1
  8. data/lib/rack/auth/abstract/request.rb +2 -2
  9. data/lib/rack/auth/basic.rb +4 -7
  10. data/lib/rack/bad_request.rb +8 -0
  11. data/lib/rack/body_proxy.rb +34 -12
  12. data/lib/rack/builder.rb +162 -59
  13. data/lib/rack/cascade.rb +24 -10
  14. data/lib/rack/common_logger.rb +43 -28
  15. data/lib/rack/conditional_get.rb +30 -25
  16. data/lib/rack/constants.rb +66 -0
  17. data/lib/rack/content_length.rb +10 -16
  18. data/lib/rack/content_type.rb +9 -7
  19. data/lib/rack/deflater.rb +78 -50
  20. data/lib/rack/directory.rb +86 -63
  21. data/lib/rack/etag.rb +14 -22
  22. data/lib/rack/events.rb +18 -17
  23. data/lib/rack/files.rb +99 -61
  24. data/lib/rack/head.rb +8 -9
  25. data/lib/rack/headers.rb +238 -0
  26. data/lib/rack/lint.rb +868 -642
  27. data/lib/rack/lock.rb +2 -6
  28. data/lib/rack/logger.rb +3 -0
  29. data/lib/rack/media_type.rb +9 -4
  30. data/lib/rack/method_override.rb +6 -2
  31. data/lib/rack/mime.rb +14 -5
  32. data/lib/rack/mock.rb +1 -253
  33. data/lib/rack/mock_request.rb +171 -0
  34. data/lib/rack/mock_response.rb +124 -0
  35. data/lib/rack/multipart/generator.rb +15 -8
  36. data/lib/rack/multipart/parser.rb +238 -107
  37. data/lib/rack/multipart/uploaded_file.rb +17 -7
  38. data/lib/rack/multipart.rb +54 -42
  39. data/lib/rack/null_logger.rb +9 -0
  40. data/lib/rack/query_parser.rb +87 -105
  41. data/lib/rack/recursive.rb +3 -1
  42. data/lib/rack/reloader.rb +0 -4
  43. data/lib/rack/request.rb +366 -135
  44. data/lib/rack/response.rb +186 -68
  45. data/lib/rack/rewindable_input.rb +24 -6
  46. data/lib/rack/runtime.rb +8 -7
  47. data/lib/rack/sendfile.rb +29 -27
  48. data/lib/rack/show_exceptions.rb +27 -12
  49. data/lib/rack/show_status.rb +21 -13
  50. data/lib/rack/static.rb +19 -12
  51. data/lib/rack/tempfile_reaper.rb +14 -5
  52. data/lib/rack/urlmap.rb +5 -6
  53. data/lib/rack/utils.rb +274 -260
  54. data/lib/rack/version.rb +21 -0
  55. data/lib/rack.rb +18 -103
  56. metadata +25 -52
  57. data/README.rdoc +0 -262
  58. data/Rakefile +0 -123
  59. data/SPEC +0 -263
  60. data/bin/rackup +0 -5
  61. data/contrib/rack.png +0 -0
  62. data/contrib/rack.svg +0 -150
  63. data/contrib/rack_logo.svg +0 -164
  64. data/contrib/rdoc.css +0 -412
  65. data/example/lobster.ru +0 -6
  66. data/example/protectedlobster.rb +0 -16
  67. data/example/protectedlobster.ru +0 -10
  68. data/lib/rack/auth/digest/md5.rb +0 -131
  69. data/lib/rack/auth/digest/nonce.rb +0 -54
  70. data/lib/rack/auth/digest/params.rb +0 -54
  71. data/lib/rack/auth/digest/request.rb +0 -43
  72. data/lib/rack/chunked.rb +0 -92
  73. data/lib/rack/core_ext/regexp.rb +0 -14
  74. data/lib/rack/file.rb +0 -8
  75. data/lib/rack/handler/cgi.rb +0 -62
  76. data/lib/rack/handler/fastcgi.rb +0 -102
  77. data/lib/rack/handler/lsws.rb +0 -63
  78. data/lib/rack/handler/scgi.rb +0 -73
  79. data/lib/rack/handler/thin.rb +0 -38
  80. data/lib/rack/handler/webrick.rb +0 -122
  81. data/lib/rack/handler.rb +0 -104
  82. data/lib/rack/lobster.rb +0 -72
  83. data/lib/rack/server.rb +0 -467
  84. data/lib/rack/session/abstract/id.rb +0 -528
  85. data/lib/rack/session/cookie.rb +0 -205
  86. data/lib/rack/session/memcache.rb +0 -10
  87. data/lib/rack/session/pool.rb +0 -85
  88. data/rack.gemspec +0 -44
@@ -1,25 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tempfile'
4
+ require 'fileutils'
5
+
3
6
  module Rack
4
7
  module Multipart
5
8
  class UploadedFile
9
+
6
10
  # The filename, *not* including the path, of the "uploaded" file
7
11
  attr_reader :original_filename
8
12
 
9
13
  # The content type of the "uploaded" file
10
14
  attr_accessor :content_type
11
15
 
12
- def initialize(path, content_type = "text/plain", binary = false)
13
- raise "#{path} file does not exist" unless ::File.exist?(path)
16
+ def initialize(filepath = nil, ct = "text/plain", bin = false,
17
+ path: filepath, content_type: ct, binary: bin, filename: nil, io: nil)
18
+ if io
19
+ @tempfile = io
20
+ @original_filename = filename
21
+ else
22
+ raise "#{path} file does not exist" unless ::File.exist?(path)
23
+ @original_filename = filename || ::File.basename(path)
24
+ @tempfile = Tempfile.new([@original_filename, ::File.extname(path)], encoding: Encoding::BINARY)
25
+ @tempfile.binmode if binary
26
+ FileUtils.copy_file(path, @tempfile.path)
27
+ end
14
28
  @content_type = content_type
15
- @original_filename = ::File.basename(path)
16
- @tempfile = Tempfile.new([@original_filename, ::File.extname(path)], encoding: Encoding::BINARY)
17
- @tempfile.binmode if binary
18
- FileUtils.copy_file(path, @tempfile.path)
19
29
  end
20
30
 
21
31
  def path
22
- @tempfile.path
32
+ @tempfile.path if @tempfile.respond_to?(:path)
23
33
  end
24
34
  alias_method :local_path, :path
25
35
 
@@ -1,65 +1,77 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rack/multipart/parser'
3
+ require_relative 'constants'
4
+ require_relative 'utils'
5
+
6
+ require_relative 'multipart/parser'
7
+ require_relative 'multipart/generator'
8
+
9
+ require_relative 'bad_request'
4
10
 
5
11
  module Rack
6
12
  # A multipart form data parser, adapted from IOWA.
7
13
  #
8
14
  # Usually, Rack::Request#POST takes care of calling this.
9
15
  module Multipart
10
- autoload :UploadedFile, 'rack/multipart/uploaded_file'
11
- autoload :Generator, 'rack/multipart/generator'
12
-
13
- EOL = "\r\n"
14
16
  MULTIPART_BOUNDARY = "AaB03x"
15
- MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni
16
- TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/
17
- CONDISP = /Content-Disposition:\s*#{TOKEN}\s*/i
18
- VALUE = /"(?:\\"|[^"])*"|#{TOKEN}/
19
- BROKEN_QUOTED = /^#{CONDISP}.*;\s*filename="(.*?)"(?:\s*$|\s*;\s*#{TOKEN}=)/i
20
- BROKEN_UNQUOTED = /^#{CONDISP}.*;\s*filename=(#{TOKEN})/i
21
- MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{EOL}/ni
22
- MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:.*;\s*name=(#{VALUE})/ni
23
- MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni
24
- # Updated definitions from RFC 2231
25
- ATTRIBUTE_CHAR = %r{[^ \t\v\n\r)(><@,;:\\"/\[\]?='*%]}
26
- ATTRIBUTE = /#{ATTRIBUTE_CHAR}+/
27
- SECTION = /\*[0-9]+/
28
- REGULAR_PARAMETER_NAME = /#{ATTRIBUTE}#{SECTION}?/
29
- REGULAR_PARAMETER = /(#{REGULAR_PARAMETER_NAME})=(#{VALUE})/
30
- EXTENDED_OTHER_NAME = /#{ATTRIBUTE}\*[1-9][0-9]*\*/
31
- EXTENDED_OTHER_VALUE = /%[0-9a-fA-F]{2}|#{ATTRIBUTE_CHAR}/
32
- EXTENDED_OTHER_PARAMETER = /(#{EXTENDED_OTHER_NAME})=(#{EXTENDED_OTHER_VALUE}*)/
33
- EXTENDED_INITIAL_NAME = /#{ATTRIBUTE}(?:\*0)?\*/
34
- EXTENDED_INITIAL_VALUE = /[a-zA-Z0-9\-]*'[a-zA-Z0-9\-]*'#{EXTENDED_OTHER_VALUE}*/
35
- EXTENDED_INITIAL_PARAMETER = /(#{EXTENDED_INITIAL_NAME})=(#{EXTENDED_INITIAL_VALUE})/
36
- EXTENDED_PARAMETER = /#{EXTENDED_INITIAL_PARAMETER}|#{EXTENDED_OTHER_PARAMETER}/
37
- DISPPARM = /;\s*(?:#{REGULAR_PARAMETER}|#{EXTENDED_PARAMETER})\s*/
38
- RFC2183 = /^#{CONDISP}(#{DISPPARM})+$/i
17
+
18
+ class MissingInputError < StandardError
19
+ include BadRequest
20
+ end
21
+
22
+ # Accumulator for multipart form data, conforming to the QueryParser API.
23
+ # In future, the Parser could return the pair list directly, but that would
24
+ # change its API.
25
+ class ParamList # :nodoc:
26
+ def self.make_params
27
+ new
28
+ end
29
+
30
+ def self.normalize_params(params, key, value)
31
+ params << [key, value]
32
+ end
33
+
34
+ def initialize
35
+ @pairs = []
36
+ end
37
+
38
+ def <<(pair)
39
+ @pairs << pair
40
+ end
41
+
42
+ def to_params_hash
43
+ @pairs
44
+ end
45
+ end
39
46
 
40
47
  class << self
41
48
  def parse_multipart(env, params = Rack::Utils.default_query_parser)
42
- extract_multipart Rack::Request.new(env), params
43
- end
49
+ unless io = env[RACK_INPUT]
50
+ raise MissingInputError, "Missing input stream!"
51
+ end
44
52
 
45
- def extract_multipart(req, params = Rack::Utils.default_query_parser)
46
- io = req.get_header(RACK_INPUT)
47
- io.rewind
48
- content_length = req.content_length
49
- content_length = content_length.to_i if content_length
53
+ if content_length = env['CONTENT_LENGTH']
54
+ content_length = content_length.to_i
55
+ end
50
56
 
51
- tempfile = req.get_header(RACK_MULTIPART_TEMPFILE_FACTORY) || Parser::TEMPFILE_FACTORY
52
- bufsize = req.get_header(RACK_MULTIPART_BUFFER_SIZE) || Parser::BUFSIZE
57
+ content_type = env['CONTENT_TYPE']
53
58
 
54
- info = Parser.parse io, content_length, req.get_header('CONTENT_TYPE'), tempfile, bufsize, params
55
- req.set_header(RACK_TEMPFILES, info.tmp_files)
56
- info.params
59
+ tempfile = env[RACK_MULTIPART_TEMPFILE_FACTORY] || Parser::TEMPFILE_FACTORY
60
+ bufsize = env[RACK_MULTIPART_BUFFER_SIZE] || Parser::BUFSIZE
61
+
62
+ info = Parser.parse(io, content_length, content_type, tempfile, bufsize, params)
63
+ env[RACK_TEMPFILES] = info.tmp_files
64
+
65
+ return info.params
66
+ end
67
+
68
+ def extract_multipart(request, params = Rack::Utils.default_query_parser)
69
+ parse_multipart(request.env)
57
70
  end
58
71
 
59
72
  def build_multipart(params, first = true)
60
73
  Generator.new(params, first).dump
61
74
  end
62
75
  end
63
-
64
76
  end
65
77
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'constants'
4
+
3
5
  module Rack
4
6
  class NullLogger
5
7
  def initialize(app)
@@ -22,6 +24,11 @@ module Rack
22
24
  def warn? ; end
23
25
  def error? ; end
24
26
  def fatal? ; end
27
+ def debug! ; end
28
+ def error! ; end
29
+ def fatal! ; end
30
+ def info! ; end
31
+ def warn! ; end
25
32
  def level ; end
26
33
  def progname ; end
27
34
  def datetime_format ; end
@@ -34,6 +41,8 @@ module Rack
34
41
  def sev_threshold=(sev_threshold); end
35
42
  def close ; end
36
43
  def add(severity, message = nil, progname = nil, &block); end
44
+ def log(severity, message = nil, progname = nil, &block); end
37
45
  def <<(msg); end
46
+ def reopen(logdev = nil); end
38
47
  end
39
48
  end
@@ -1,46 +1,53 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'core_ext/regexp'
3
+ require_relative 'bad_request'
4
+ require 'uri'
4
5
 
5
6
  module Rack
6
7
  class QueryParser
7
- using ::Rack::RegexpExtensions
8
-
9
- DEFAULT_SEP = /[&;] */n
10
- COMMON_SEP = { ";" => /[;] */n, ";," => /[;,] */n, "&" => /[&] */n }
8
+ DEFAULT_SEP = /& */n
9
+ COMMON_SEP = { ";" => /; */n, ";," => /[;,] */n, "&" => /& */n }
11
10
 
12
11
  # ParameterTypeError is the error that is raised when incoming structural
13
12
  # parameters (parsed by parse_nested_query) contain conflicting types.
14
- class ParameterTypeError < TypeError; end
13
+ class ParameterTypeError < TypeError
14
+ include BadRequest
15
+ end
15
16
 
16
17
  # InvalidParameterError is the error that is raised when incoming structural
17
18
  # parameters (parsed by parse_nested_query) contain invalid format or byte
18
19
  # sequence.
19
- class InvalidParameterError < ArgumentError; end
20
+ class InvalidParameterError < ArgumentError
21
+ include BadRequest
22
+ end
20
23
 
21
- def self.make_default(key_space_limit, param_depth_limit)
22
- new Params, key_space_limit, param_depth_limit
24
+ # ParamsTooDeepError is the error that is raised when params are recursively
25
+ # nested over the specified limit.
26
+ class ParamsTooDeepError < RangeError
27
+ include BadRequest
23
28
  end
24
29
 
25
- attr_reader :key_space_limit, :param_depth_limit
30
+ def self.make_default(param_depth_limit)
31
+ new Params, param_depth_limit
32
+ end
26
33
 
27
- def initialize(params_class, key_space_limit, param_depth_limit)
34
+ attr_reader :param_depth_limit
35
+
36
+ def initialize(params_class, param_depth_limit)
28
37
  @params_class = params_class
29
- @key_space_limit = key_space_limit
30
38
  @param_depth_limit = param_depth_limit
31
39
  end
32
40
 
33
41
  # Stolen from Mongrel, with some small modifications:
34
- # Parses a query string by breaking it up at the '&'
35
- # and ';' characters. You can also use this to parse
36
- # cookies by changing the characters used in the second
37
- # parameter (which defaults to '&;').
38
- def parse_query(qs, d = nil, &unescaper)
42
+ # Parses a query string by breaking it up at the '&'. You can also use this
43
+ # to parse cookies by changing the characters used in the second parameter
44
+ # (which defaults to '&').
45
+ def parse_query(qs, separator = nil, &unescaper)
39
46
  unescaper ||= method(:unescape)
40
47
 
41
48
  params = make_params
42
49
 
43
- (qs || '').split(d ? (COMMON_SEP[d] || /[#{d}] */n) : DEFAULT_SEP).each do |p|
50
+ (qs || '').split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
44
51
  next if p.empty?
45
52
  k, v = p.split('=', 2).map!(&unescaper)
46
53
 
@@ -63,75 +70,105 @@ module Rack
63
70
  # query strings with parameters of conflicting types, in this case a
64
71
  # ParameterTypeError is raised. Users are encouraged to return a 400 in this
65
72
  # case.
66
- def parse_nested_query(qs, d = nil)
67
- return {} if qs.nil? || qs.empty?
73
+ def parse_nested_query(qs, separator = nil)
68
74
  params = make_params
69
75
 
70
- qs.split(d ? (COMMON_SEP[d] || /[#{d}] */n) : DEFAULT_SEP).each do |p|
71
- k, v = p.split('=', 2).map! { |s| unescape(s) }
76
+ unless qs.nil? || qs.empty?
77
+ (qs || '').split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p|
78
+ k, v = p.split('=', 2).map! { |s| unescape(s) }
72
79
 
73
- normalize_params(params, k, v, param_depth_limit)
80
+ _normalize_params(params, k, v, 0)
81
+ end
74
82
  end
75
83
 
76
84
  return params.to_h
77
85
  rescue ArgumentError => e
78
- raise InvalidParameterError, e.message
86
+ raise InvalidParameterError, e.message, e.backtrace
79
87
  end
80
88
 
81
89
  # normalize_params recursively expands parameters into structural types. If
82
90
  # the structural types represented by two different parameter names are in
83
- # conflict, a ParameterTypeError is raised.
84
- def normalize_params(params, name, v, depth)
85
- raise RangeError if depth <= 0
86
-
87
- name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
88
- k = $1 || ''
89
- after = $' || ''
91
+ # conflict, a ParameterTypeError is raised. The depth argument is deprecated
92
+ # and should no longer be used, it is kept for backwards compatibility with
93
+ # earlier versions of rack.
94
+ def normalize_params(params, name, v, _depth=nil)
95
+ _normalize_params(params, name, v, 0)
96
+ end
90
97
 
91
- if k.empty?
92
- if !v.nil? && name == "[]"
93
- return Array(v)
98
+ private def _normalize_params(params, name, v, depth)
99
+ raise ParamsTooDeepError if depth >= param_depth_limit
100
+
101
+ if !name
102
+ # nil name, treat same as empty string (required by tests)
103
+ k = after = ''
104
+ elsif depth == 0
105
+ # Start of parsing, don't treat [] or [ at start of string specially
106
+ if start = name.index('[', 1)
107
+ # Start of parameter nesting, use part before brackets as key
108
+ k = name[0, start]
109
+ after = name[start, name.length]
94
110
  else
95
- return
111
+ # Plain parameter with no nesting
112
+ k = name
113
+ after = ''
96
114
  end
115
+ elsif name.start_with?('[]')
116
+ # Array nesting
117
+ k = '[]'
118
+ after = name[2, name.length]
119
+ elsif name.start_with?('[') && (start = name.index(']', 1))
120
+ # Hash nesting, use the part inside brackets as the key
121
+ k = name[1, start-1]
122
+ after = name[start+1, name.length]
123
+ else
124
+ # Probably malformed input, nested but not starting with [
125
+ # treat full name as key for backwards compatibility.
126
+ k = name
127
+ after = ''
97
128
  end
98
129
 
130
+ return if k.empty?
131
+
99
132
  if after == ''
100
- params[k] = v
133
+ if k == '[]' && depth != 0
134
+ return [v]
135
+ else
136
+ params[k] = v
137
+ end
101
138
  elsif after == "["
102
139
  params[name] = v
103
140
  elsif after == "[]"
104
141
  params[k] ||= []
105
142
  raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
106
143
  params[k] << v
107
- elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
108
- child_key = $1
144
+ elsif after.start_with?('[]')
145
+ # Recognize x[][y] (hash inside array) parameters
146
+ unless after[2] == '[' && after.end_with?(']') && (child_key = after[3, after.length-4]) && !child_key.empty? && !child_key.index('[') && !child_key.index(']')
147
+ # Handle other nested array parameters
148
+ child_key = after[2, after.length]
149
+ end
109
150
  params[k] ||= []
110
151
  raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
111
152
  if params_hash_type?(params[k].last) && !params_hash_has_key?(params[k].last, child_key)
112
- normalize_params(params[k].last, child_key, v, depth - 1)
153
+ _normalize_params(params[k].last, child_key, v, depth + 1)
113
154
  else
114
- params[k] << normalize_params(make_params, child_key, v, depth - 1)
155
+ params[k] << _normalize_params(make_params, child_key, v, depth + 1)
115
156
  end
116
157
  else
117
158
  params[k] ||= make_params
118
159
  raise ParameterTypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params_hash_type?(params[k])
119
- params[k] = normalize_params(params[k], after, v, depth - 1)
160
+ params[k] = _normalize_params(params[k], after, v, depth + 1)
120
161
  end
121
162
 
122
163
  params
123
164
  end
124
165
 
125
166
  def make_params
126
- @params_class.new @key_space_limit
127
- end
128
-
129
- def new_space_limit(key_space_limit)
130
- self.class.new @params_class, key_space_limit, param_depth_limit
167
+ @params_class.new
131
168
  end
132
169
 
133
170
  def new_depth_limit(param_depth_limit)
134
- self.class.new @params_class, key_space_limit, param_depth_limit
171
+ self.class.new @params_class, param_depth_limit
135
172
  end
136
173
 
137
174
  private
@@ -152,66 +189,11 @@ module Rack
152
189
  true
153
190
  end
154
191
 
155
- def unescape(s)
156
- Utils.unescape(s)
192
+ def unescape(string, encoding = Encoding::UTF_8)
193
+ URI.decode_www_form_component(string, encoding)
157
194
  end
158
195
 
159
- class Params
160
- def initialize(limit)
161
- @limit = limit
162
- @size = 0
163
- @params = {}
164
- end
165
-
166
- def [](key)
167
- @params[key]
168
- end
169
-
170
- def []=(key, value)
171
- @size += key.size if key && !@params.key?(key)
172
- raise RangeError, 'exceeded available parameter key space' if @size > @limit
173
- @params[key] = value
174
- end
175
-
176
- def key?(key)
177
- @params.key?(key)
178
- end
179
-
180
- # Recursively unwraps nested `Params` objects and constructs an object
181
- # of the same shape, but using the objects' internal representations
182
- # (Ruby hashes) in place of the objects. The result is a hash consisting
183
- # purely of Ruby primitives.
184
- #
185
- # Mutation warning!
186
- #
187
- # 1. This method mutates the internal representation of the `Params`
188
- # objects in order to save object allocations.
189
- #
190
- # 2. The value you get back is a reference to the internal hash
191
- # representation, not a copy.
192
- #
193
- # 3. Because the `Params` object's internal representation is mutable
194
- # through the `#[]=` method, it is not thread safe. The result of
195
- # getting the hash representation while another thread is adding a
196
- # key to it is non-deterministic.
197
- #
198
- def to_h
199
- @params.each do |key, value|
200
- case value
201
- when self
202
- # Handle circular references gracefully.
203
- @params[key] = @params
204
- when Params
205
- @params[key] = value.to_h
206
- when Array
207
- value.map! { |v| v.kind_of?(Params) ? v.to_h : v }
208
- else
209
- # Ignore anything that is not a `Params` object or
210
- # a collection that can contain one.
211
- end
212
- end
213
- @params
214
- end
196
+ class Params < Hash
215
197
  alias_method :to_params_hash, :to_h
216
198
  end
217
199
  end
@@ -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+.
@@ -19,7 +21,7 @@ module Rack
19
21
  @env[PATH_INFO] = @url.path
20
22
  @env[QUERY_STRING] = @url.query if @url.query
21
23
  @env[HTTP_HOST] = @url.host if @url.host
22
- @env["HTTP_PORT"] = @url.port if @url.port
24
+ @env[HTTP_PORT] = @url.port if @url.port
23
25
  @env[RACK_URL_SCHEME] = @url.scheme if @url.scheme
24
26
 
25
27
  super "forwarding to #{url}"
data/lib/rack/reloader.rb CHANGED
@@ -6,8 +6,6 @@
6
6
 
7
7
  require 'pathname'
8
8
 
9
- require_relative 'core_ext/regexp'
10
-
11
9
  module Rack
12
10
 
13
11
  # High performant source reloader
@@ -24,8 +22,6 @@ module Rack
24
22
  # It is performing a check/reload cycle at the start of every request, but
25
23
  # also respects a cool down time, during which nothing will be done.
26
24
  class Reloader
27
- using ::Rack::RegexpExtensions
28
-
29
25
  def initialize(app, cooldown = 10, backend = Stat)
30
26
  @app = app
31
27
  @cooldown = cooldown