rack 3.0.8 → 3.1.13
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 +256 -2
- data/CONTRIBUTING.md +11 -9
- data/README.md +34 -15
- data/SPEC.rdoc +38 -13
- data/lib/rack/auth/basic.rb +1 -2
- data/lib/rack/bad_request.rb +8 -0
- data/lib/rack/body_proxy.rb +18 -2
- data/lib/rack/builder.rb +23 -10
- data/lib/rack/cascade.rb +0 -3
- data/lib/rack/common_logger.rb +3 -2
- data/lib/rack/constants.rb +3 -0
- data/lib/rack/etag.rb +3 -0
- data/lib/rack/headers.rb +86 -2
- data/lib/rack/lint.rb +118 -34
- data/lib/rack/logger.rb +2 -1
- data/lib/rack/media_type.rb +17 -7
- data/lib/rack/mime.rb +6 -5
- data/lib/rack/mock_request.rb +10 -15
- data/lib/rack/mock_response.rb +14 -16
- data/lib/rack/multipart/parser.rb +131 -63
- data/lib/rack/multipart.rb +34 -1
- data/lib/rack/query_parser.rb +15 -68
- data/lib/rack/request.rb +40 -21
- data/lib/rack/response.rb +29 -19
- data/lib/rack/sendfile.rb +1 -1
- data/lib/rack/show_exceptions.rb +6 -2
- data/lib/rack/static.rb +2 -1
- data/lib/rack/utils.rb +80 -103
- data/lib/rack/version.rb +1 -14
- data/lib/rack.rb +10 -16
- metadata +4 -13
- data/lib/rack/auth/digest/md5.rb +0 -1
- data/lib/rack/auth/digest/nonce.rb +0 -1
- data/lib/rack/auth/digest/params.rb +0 -1
- data/lib/rack/auth/digest/request.rb +0 -1
- data/lib/rack/auth/digest.rb +0 -256
- data/lib/rack/chunked.rb +0 -120
- data/lib/rack/file.rb +0 -9
data/lib/rack/response.rb
CHANGED
|
@@ -31,13 +31,6 @@ module Rack
|
|
|
31
31
|
attr_accessor :length, :status, :body
|
|
32
32
|
attr_reader :headers
|
|
33
33
|
|
|
34
|
-
# Deprecated, use headers instead.
|
|
35
|
-
def header
|
|
36
|
-
warn 'Rack::Response#header is deprecated and will be removed in Rack 3.1', uplevel: 1
|
|
37
|
-
|
|
38
|
-
headers
|
|
39
|
-
end
|
|
40
|
-
|
|
41
34
|
# Initialize the response object with the specified +body+, +status+
|
|
42
35
|
# and +headers+.
|
|
43
36
|
#
|
|
@@ -62,7 +55,7 @@ module Rack
|
|
|
62
55
|
@status = status.to_i
|
|
63
56
|
|
|
64
57
|
unless headers.is_a?(Hash)
|
|
65
|
-
|
|
58
|
+
raise ArgumentError, "Headers must be a Hash!"
|
|
66
59
|
end
|
|
67
60
|
|
|
68
61
|
@headers = Headers.new
|
|
@@ -79,7 +72,8 @@ module Rack
|
|
|
79
72
|
if body.nil?
|
|
80
73
|
@body = []
|
|
81
74
|
@buffered = true
|
|
82
|
-
|
|
75
|
+
# Body is unspecified - it may be a buffered response, or it may be a HEAD response.
|
|
76
|
+
@length = nil
|
|
83
77
|
elsif body.respond_to?(:to_str)
|
|
84
78
|
@body = [body]
|
|
85
79
|
@buffered = true
|
|
@@ -87,7 +81,7 @@ module Rack
|
|
|
87
81
|
else
|
|
88
82
|
@body = body
|
|
89
83
|
@buffered = nil # undetermined as of yet.
|
|
90
|
-
@length =
|
|
84
|
+
@length = nil
|
|
91
85
|
end
|
|
92
86
|
|
|
93
87
|
yield self if block_given?
|
|
@@ -106,7 +100,7 @@ module Rack
|
|
|
106
100
|
# The response body is an enumerable body and it is not allowed to have an entity body.
|
|
107
101
|
@body.respond_to?(:each) && STATUS_WITH_NO_ENTITY_BODY[@status]
|
|
108
102
|
end
|
|
109
|
-
|
|
103
|
+
|
|
110
104
|
# Generate a response array consistent with the requirements of the SPEC.
|
|
111
105
|
# @return [Array] a 3-tuple suitable of `[status, headers, body]`
|
|
112
106
|
# which is suitable to be returned from the middleware `#call(env)` method.
|
|
@@ -118,9 +112,14 @@ module Rack
|
|
|
118
112
|
return [@status, @headers, []]
|
|
119
113
|
else
|
|
120
114
|
if block_given?
|
|
115
|
+
# We don't add the content-length here as the user has provided a block that can #write additional chunks to the body.
|
|
121
116
|
@block = block
|
|
122
117
|
return [@status, @headers, self]
|
|
123
118
|
else
|
|
119
|
+
# If we know the length of the body, set the content-length header... except if we are chunked? which is a legacy special case where the body might already be encoded and thus the actual encoded body length and the content-length are likely to be different.
|
|
120
|
+
if @length && !chunked?
|
|
121
|
+
@headers[CONTENT_LENGTH] = @length.to_s
|
|
122
|
+
end
|
|
124
123
|
return [@status, @headers, @body]
|
|
125
124
|
end
|
|
126
125
|
end
|
|
@@ -138,7 +137,9 @@ module Rack
|
|
|
138
137
|
end
|
|
139
138
|
end
|
|
140
139
|
|
|
141
|
-
# Append to
|
|
140
|
+
# Append a chunk to the response body.
|
|
141
|
+
#
|
|
142
|
+
# Converts the response into a buffered response if it wasn't already.
|
|
142
143
|
#
|
|
143
144
|
# NOTE: Do not mix #write and direct #body access!
|
|
144
145
|
#
|
|
@@ -320,27 +321,34 @@ module Rack
|
|
|
320
321
|
|
|
321
322
|
protected
|
|
322
323
|
|
|
324
|
+
# Convert the body of this response into an internally buffered Array if possible.
|
|
325
|
+
#
|
|
326
|
+
# `@buffered` is a ternary value which indicates whether the body is buffered. It can be:
|
|
327
|
+
# * `nil` - The body has not been buffered yet.
|
|
328
|
+
# * `true` - The body is buffered as an Array instance.
|
|
329
|
+
# * `false` - The body is not buffered and cannot be buffered.
|
|
330
|
+
#
|
|
331
|
+
# @return [Boolean] whether the body is buffered as an Array instance.
|
|
323
332
|
def buffered_body!
|
|
324
333
|
if @buffered.nil?
|
|
325
334
|
if @body.is_a?(Array)
|
|
326
335
|
# The user supplied body was an array:
|
|
327
336
|
@body = @body.compact
|
|
328
|
-
@body.
|
|
329
|
-
|
|
330
|
-
end
|
|
337
|
+
@length = @body.sum{|part| part.bytesize}
|
|
338
|
+
@buffered = true
|
|
331
339
|
elsif @body.respond_to?(:each)
|
|
332
340
|
# Turn the user supplied body into a buffered array:
|
|
333
341
|
body = @body
|
|
334
342
|
@body = Array.new
|
|
343
|
+
@buffered = true
|
|
335
344
|
|
|
336
345
|
body.each do |part|
|
|
337
346
|
@writer.call(part.to_s)
|
|
338
347
|
end
|
|
339
348
|
|
|
340
349
|
body.close if body.respond_to?(:close)
|
|
341
|
-
|
|
342
|
-
@buffered = true
|
|
343
350
|
else
|
|
351
|
+
# We don't know how to buffer the user-supplied body:
|
|
344
352
|
@buffered = false
|
|
345
353
|
end
|
|
346
354
|
end
|
|
@@ -349,11 +357,13 @@ module Rack
|
|
|
349
357
|
end
|
|
350
358
|
|
|
351
359
|
def append(chunk)
|
|
360
|
+
chunk = chunk.dup unless chunk.frozen?
|
|
352
361
|
@body << chunk
|
|
353
362
|
|
|
354
|
-
|
|
363
|
+
if @length
|
|
355
364
|
@length += chunk.bytesize
|
|
356
|
-
|
|
365
|
+
elsif @buffered
|
|
366
|
+
@length = chunk.bytesize
|
|
357
367
|
end
|
|
358
368
|
|
|
359
369
|
return chunk
|
data/lib/rack/sendfile.rb
CHANGED
data/lib/rack/show_exceptions.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'ostruct'
|
|
4
3
|
require 'erb'
|
|
5
4
|
|
|
6
5
|
require_relative 'constants'
|
|
@@ -19,6 +18,11 @@ module Rack
|
|
|
19
18
|
class ShowExceptions
|
|
20
19
|
CONTEXT = 7
|
|
21
20
|
|
|
21
|
+
Frame = Struct.new(:filename, :lineno, :function,
|
|
22
|
+
:pre_context_lineno, :pre_context,
|
|
23
|
+
:context_line, :post_context_lineno,
|
|
24
|
+
:post_context)
|
|
25
|
+
|
|
22
26
|
def initialize(app)
|
|
23
27
|
@app = app
|
|
24
28
|
end
|
|
@@ -79,7 +83,7 @@ module Rack
|
|
|
79
83
|
# This double assignment is to prevent an "unused variable" warning.
|
|
80
84
|
# Yes, it is dumb, but I don't like Ruby yelling at me.
|
|
81
85
|
frames = frames = exception.backtrace.map { |line|
|
|
82
|
-
frame =
|
|
86
|
+
frame = Frame.new
|
|
83
87
|
if line =~ /(.*?):(\d+)(:in `(.*)')?/
|
|
84
88
|
frame.filename = $1
|
|
85
89
|
frame.lineno = $2.to_i
|
data/lib/rack/static.rb
CHANGED
|
@@ -124,8 +124,9 @@ module Rack
|
|
|
124
124
|
|
|
125
125
|
def call(env)
|
|
126
126
|
path = env[PATH_INFO]
|
|
127
|
+
actual_path = Utils.clean_path_info(Utils.unescape_path(path))
|
|
127
128
|
|
|
128
|
-
if can_serve(
|
|
129
|
+
if can_serve(actual_path)
|
|
129
130
|
if overwrite_file_path(path)
|
|
130
131
|
env[PATH_INFO] = (add_index_root?(path) ? path + @index : @urls[path])
|
|
131
132
|
elsif @gzip && env['HTTP_ACCEPT_ENCODING'] && /\bgzip\b/.match?(env['HTTP_ACCEPT_ENCODING'])
|
data/lib/rack/utils.rb
CHANGED
|
@@ -6,6 +6,7 @@ require 'fileutils'
|
|
|
6
6
|
require 'set'
|
|
7
7
|
require 'tempfile'
|
|
8
8
|
require 'time'
|
|
9
|
+
require 'erb'
|
|
9
10
|
|
|
10
11
|
require_relative 'query_parser'
|
|
11
12
|
require_relative 'mime'
|
|
@@ -23,6 +24,7 @@ module Rack
|
|
|
23
24
|
DEFAULT_SEP = QueryParser::DEFAULT_SEP
|
|
24
25
|
COMMON_SEP = QueryParser::COMMON_SEP
|
|
25
26
|
KeySpaceConstrainedParams = QueryParser::Params
|
|
27
|
+
URI_PARSER = defined?(::URI::RFC2396_PARSER) ? ::URI::RFC2396_PARSER : ::URI::DEFAULT_PARSER
|
|
26
28
|
|
|
27
29
|
class << self
|
|
28
30
|
attr_accessor :default_query_parser
|
|
@@ -42,13 +44,13 @@ module Rack
|
|
|
42
44
|
# Like URI escaping, but with %20 instead of +. Strictly speaking this is
|
|
43
45
|
# true URI escaping.
|
|
44
46
|
def escape_path(s)
|
|
45
|
-
|
|
47
|
+
URI_PARSER.escape s
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
# Unescapes the **path** component of a URI. See Rack::Utils.unescape for
|
|
49
51
|
# unescaping query parameters or form components.
|
|
50
52
|
def unescape_path(s)
|
|
51
|
-
|
|
53
|
+
URI_PARSER.unescape s
|
|
52
54
|
end
|
|
53
55
|
|
|
54
56
|
# Unescapes a URI escaped string with +encoding+. +encoding+ will be the
|
|
@@ -85,15 +87,6 @@ module Rack
|
|
|
85
87
|
self.default_query_parser = self.default_query_parser.new_depth_limit(v)
|
|
86
88
|
end
|
|
87
89
|
|
|
88
|
-
def self.key_space_limit
|
|
89
|
-
warn("`Rack::Utils.key_space_limit` is deprecated as this value no longer has an effect. It will be removed in Rack 3.1", uplevel: 1)
|
|
90
|
-
65536
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def self.key_space_limit=(v)
|
|
94
|
-
warn("`Rack::Utils.key_space_limit=` is deprecated and no longer has an effect. It will be removed in Rack 3.1", uplevel: 1)
|
|
95
|
-
end
|
|
96
|
-
|
|
97
90
|
if defined?(Process::CLOCK_MONOTONIC)
|
|
98
91
|
def clock_time
|
|
99
92
|
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
@@ -143,8 +136,8 @@ module Rack
|
|
|
143
136
|
end
|
|
144
137
|
|
|
145
138
|
def q_values(q_value_header)
|
|
146
|
-
q_value_header.to_s.split(
|
|
147
|
-
value, parameters = part.split(
|
|
139
|
+
q_value_header.to_s.split(',').map do |part|
|
|
140
|
+
value, parameters = part.split(';', 2).map(&:strip)
|
|
148
141
|
quality = 1.0
|
|
149
142
|
if parameters && (md = /\Aq=([\d.]+)/.match(parameters))
|
|
150
143
|
quality = md[1].to_f
|
|
@@ -157,9 +150,10 @@ module Rack
|
|
|
157
150
|
return nil unless forwarded_header
|
|
158
151
|
forwarded_header = forwarded_header.to_s.gsub("\n", ";")
|
|
159
152
|
|
|
160
|
-
forwarded_header.split(
|
|
161
|
-
field.split(
|
|
162
|
-
|
|
153
|
+
forwarded_header.split(';').each_with_object({}) do |field, values|
|
|
154
|
+
field.split(',').each do |pair|
|
|
155
|
+
pair = pair.split('=').map(&:strip).join('=')
|
|
156
|
+
return nil unless pair =~ /\A(by|for|host|proto)="?([^"]+)"?\Z/i
|
|
163
157
|
(values[$1.downcase.to_sym] ||= []) << $2
|
|
164
158
|
end
|
|
165
159
|
end
|
|
@@ -183,20 +177,16 @@ module Rack
|
|
|
183
177
|
matches&.first
|
|
184
178
|
end
|
|
185
179
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
'
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
# Escape ampersands, brackets and quotes to their HTML/XML entities.
|
|
198
|
-
def escape_html(string)
|
|
199
|
-
string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
|
|
180
|
+
# Introduced in ERB 4.0. ERB::Escape is an alias for ERB::Utils which
|
|
181
|
+
# doesn't get monkey-patched by rails
|
|
182
|
+
if defined?(ERB::Escape) && ERB::Escape.instance_method(:html_escape)
|
|
183
|
+
define_method(:escape_html, ERB::Escape.instance_method(:html_escape))
|
|
184
|
+
else
|
|
185
|
+
require 'cgi/escape'
|
|
186
|
+
# Escape ampersands, brackets and quotes to their HTML/XML entities.
|
|
187
|
+
def escape_html(string)
|
|
188
|
+
CGI.escapeHTML(string.to_s)
|
|
189
|
+
end
|
|
200
190
|
end
|
|
201
191
|
|
|
202
192
|
def select_best_encoding(available_encodings, accept_encoding)
|
|
@@ -251,21 +241,6 @@ module Rack
|
|
|
251
241
|
end
|
|
252
242
|
end
|
|
253
243
|
|
|
254
|
-
def add_cookie_to_header(header, key, value)
|
|
255
|
-
warn("add_cookie_to_header is deprecated and will be removed in Rack 3.1", uplevel: 1)
|
|
256
|
-
|
|
257
|
-
case header
|
|
258
|
-
when nil, ''
|
|
259
|
-
return set_cookie_header(key, value)
|
|
260
|
-
when String
|
|
261
|
-
[header, set_cookie_header(key, value)]
|
|
262
|
-
when Array
|
|
263
|
-
header + [set_cookie_header(key, value)]
|
|
264
|
-
else
|
|
265
|
-
raise ArgumentError, "Unrecognized cookie header value. Expected String, Array, or nil, got #{header.inspect}"
|
|
266
|
-
end
|
|
267
|
-
end
|
|
268
|
-
|
|
269
244
|
# :call-seq:
|
|
270
245
|
# parse_cookies(env) -> hash
|
|
271
246
|
#
|
|
@@ -279,6 +254,20 @@ module Rack
|
|
|
279
254
|
parse_cookies_header env[HTTP_COOKIE]
|
|
280
255
|
end
|
|
281
256
|
|
|
257
|
+
# A valid cookie key according to RFC2616.
|
|
258
|
+
# A <cookie-name> can be any US-ASCII characters, except control characters, spaces, or tabs. It also must not contain a separator character like the following: ( ) < > @ , ; : \ " / [ ] ? = { }.
|
|
259
|
+
VALID_COOKIE_KEY = /\A[!#$%&'*+\-\.\^_`|~0-9a-zA-Z]+\z/.freeze
|
|
260
|
+
private_constant :VALID_COOKIE_KEY
|
|
261
|
+
|
|
262
|
+
private def escape_cookie_key(key)
|
|
263
|
+
if key =~ VALID_COOKIE_KEY
|
|
264
|
+
key
|
|
265
|
+
else
|
|
266
|
+
warn "Cookie key #{key.inspect} is not valid according to RFC2616; it will be escaped. This behaviour is deprecated and will be removed in a future version of Rack.", uplevel: 2
|
|
267
|
+
escape(key)
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
282
271
|
# :call-seq:
|
|
283
272
|
# set_cookie_header(key, value) -> encoded string
|
|
284
273
|
#
|
|
@@ -305,7 +294,7 @@ module Rack
|
|
|
305
294
|
def set_cookie_header(key, value)
|
|
306
295
|
case value
|
|
307
296
|
when Hash
|
|
308
|
-
key =
|
|
297
|
+
key = escape_cookie_key(key) unless value[:escape_key] == false
|
|
309
298
|
domain = "; domain=#{value[:domain]}" if value[:domain]
|
|
310
299
|
path = "; path=#{value[:path]}" if value[:path]
|
|
311
300
|
max_age = "; max-age=#{value[:max_age]}" if value[:max_age]
|
|
@@ -317,23 +306,24 @@ module Rack
|
|
|
317
306
|
when false, nil
|
|
318
307
|
nil
|
|
319
308
|
when :none, 'None', :None
|
|
320
|
-
';
|
|
309
|
+
'; samesite=none'
|
|
321
310
|
when :lax, 'Lax', :Lax
|
|
322
|
-
';
|
|
311
|
+
'; samesite=lax'
|
|
323
312
|
when true, :strict, 'Strict', :Strict
|
|
324
|
-
';
|
|
313
|
+
'; samesite=strict'
|
|
325
314
|
else
|
|
326
|
-
raise ArgumentError, "Invalid
|
|
315
|
+
raise ArgumentError, "Invalid :same_site value: #{value[:same_site].inspect}"
|
|
327
316
|
end
|
|
317
|
+
partitioned = "; partitioned" if value[:partitioned]
|
|
328
318
|
value = value[:value]
|
|
329
319
|
else
|
|
330
|
-
key =
|
|
320
|
+
key = escape_cookie_key(key)
|
|
331
321
|
end
|
|
332
322
|
|
|
333
323
|
value = [value] unless Array === value
|
|
334
324
|
|
|
335
325
|
return "#{key}=#{value.map { |v| escape v }.join('&')}#{domain}" \
|
|
336
|
-
"#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}"
|
|
326
|
+
"#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}#{partitioned}"
|
|
337
327
|
end
|
|
338
328
|
|
|
339
329
|
# :call-seq:
|
|
@@ -374,24 +364,12 @@ module Rack
|
|
|
374
364
|
set_cookie_header(key, value.merge(max_age: '0', expires: Time.at(0), value: ''))
|
|
375
365
|
end
|
|
376
366
|
|
|
377
|
-
def make_delete_cookie_header(header, key, value)
|
|
378
|
-
warn("make_delete_cookie_header is deprecated and will be removed in Rack 3.1, use delete_set_cookie_header! instead", uplevel: 1)
|
|
379
|
-
|
|
380
|
-
delete_set_cookie_header!(header, key, value)
|
|
381
|
-
end
|
|
382
|
-
|
|
383
367
|
def delete_cookie_header!(headers, key, value = {})
|
|
384
368
|
headers[SET_COOKIE] = delete_set_cookie_header!(headers[SET_COOKIE], key, value)
|
|
385
369
|
|
|
386
370
|
return nil
|
|
387
371
|
end
|
|
388
372
|
|
|
389
|
-
def add_remove_cookie_to_header(header, key, value = {})
|
|
390
|
-
warn("add_remove_cookie_to_header is deprecated and will be removed in Rack 3.1, use delete_set_cookie_header! instead", uplevel: 1)
|
|
391
|
-
|
|
392
|
-
delete_set_cookie_header!(header, key, value)
|
|
393
|
-
end
|
|
394
|
-
|
|
395
373
|
# :call-seq:
|
|
396
374
|
# delete_set_cookie_header!(header, key, value = {}) -> header value
|
|
397
375
|
#
|
|
@@ -434,6 +412,8 @@ module Rack
|
|
|
434
412
|
|
|
435
413
|
def get_byte_ranges(http_range, size)
|
|
436
414
|
# See <http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35>
|
|
415
|
+
# Ignore Range when file size is 0 to avoid a 416 error.
|
|
416
|
+
return nil if size.zero?
|
|
437
417
|
return nil unless http_range && http_range =~ /bytes=([^;]+)/
|
|
438
418
|
ranges = []
|
|
439
419
|
$1.split(/,\s*/).each do |range_spec|
|
|
@@ -458,6 +438,9 @@ module Rack
|
|
|
458
438
|
end
|
|
459
439
|
ranges << (r0..r1) if r0 <= r1
|
|
460
440
|
end
|
|
441
|
+
|
|
442
|
+
return [] if ranges.map(&:size).sum > size
|
|
443
|
+
|
|
461
444
|
ranges
|
|
462
445
|
end
|
|
463
446
|
|
|
@@ -513,39 +496,12 @@ module Rack
|
|
|
513
496
|
end
|
|
514
497
|
end
|
|
515
498
|
|
|
516
|
-
# A wrapper around Headers
|
|
517
|
-
# header when set.
|
|
518
|
-
#
|
|
519
|
-
# @api private
|
|
520
|
-
class HeaderHash < Hash # :nodoc:
|
|
521
|
-
def self.[](headers)
|
|
522
|
-
warn "Rack::Utils::HeaderHash is deprecated and will be removed in Rack 3.1, switch to Rack::Headers", uplevel: 1
|
|
523
|
-
if headers.is_a?(Headers) && !headers.frozen?
|
|
524
|
-
return headers
|
|
525
|
-
end
|
|
526
|
-
|
|
527
|
-
new_headers = Headers.new
|
|
528
|
-
headers.each{|k,v| new_headers[k] = v}
|
|
529
|
-
new_headers
|
|
530
|
-
end
|
|
531
|
-
|
|
532
|
-
def self.new(hash = {})
|
|
533
|
-
warn "Rack::Utils::HeaderHash is deprecated and will be removed in Rack 3.1, switch to Rack::Headers", uplevel: 1
|
|
534
|
-
headers = Headers.new
|
|
535
|
-
hash.each{|k,v| headers[k] = v}
|
|
536
|
-
headers
|
|
537
|
-
end
|
|
538
|
-
|
|
539
|
-
def self.allocate
|
|
540
|
-
raise TypeError, "cannot allocate HeaderHash"
|
|
541
|
-
end
|
|
542
|
-
end
|
|
543
|
-
|
|
544
499
|
# Every standard HTTP code mapped to the appropriate message.
|
|
545
500
|
# Generated with:
|
|
546
|
-
# curl -s https://www.iana.org/assignments/http-status-codes/http-status-codes-1.csv
|
|
547
|
-
# ruby -
|
|
548
|
-
#
|
|
501
|
+
# curl -s https://www.iana.org/assignments/http-status-codes/http-status-codes-1.csv \
|
|
502
|
+
# | ruby -rcsv -e "puts CSV.parse(STDIN, headers: true) \
|
|
503
|
+
# .reject {|v| v['Description'] == 'Unassigned' or v['Description'].include? '(' } \
|
|
504
|
+
# .map {|v| %Q/#{v['Value']} => '#{v['Description']}'/ }.join(','+?\n)"
|
|
549
505
|
HTTP_STATUS_CODES = {
|
|
550
506
|
100 => 'Continue',
|
|
551
507
|
101 => 'Switching Protocols',
|
|
@@ -567,7 +523,6 @@ module Rack
|
|
|
567
523
|
303 => 'See Other',
|
|
568
524
|
304 => 'Not Modified',
|
|
569
525
|
305 => 'Use Proxy',
|
|
570
|
-
306 => '(Unused)',
|
|
571
526
|
307 => 'Temporary Redirect',
|
|
572
527
|
308 => 'Permanent Redirect',
|
|
573
528
|
400 => 'Bad Request',
|
|
@@ -583,13 +538,13 @@ module Rack
|
|
|
583
538
|
410 => 'Gone',
|
|
584
539
|
411 => 'Length Required',
|
|
585
540
|
412 => 'Precondition Failed',
|
|
586
|
-
413 => '
|
|
541
|
+
413 => 'Content Too Large',
|
|
587
542
|
414 => 'URI Too Long',
|
|
588
543
|
415 => 'Unsupported Media Type',
|
|
589
544
|
416 => 'Range Not Satisfiable',
|
|
590
545
|
417 => 'Expectation Failed',
|
|
591
546
|
421 => 'Misdirected Request',
|
|
592
|
-
422 => 'Unprocessable
|
|
547
|
+
422 => 'Unprocessable Content',
|
|
593
548
|
423 => 'Locked',
|
|
594
549
|
424 => 'Failed Dependency',
|
|
595
550
|
425 => 'Too Early',
|
|
@@ -597,7 +552,7 @@ module Rack
|
|
|
597
552
|
428 => 'Precondition Required',
|
|
598
553
|
429 => 'Too Many Requests',
|
|
599
554
|
431 => 'Request Header Fields Too Large',
|
|
600
|
-
451 => 'Unavailable
|
|
555
|
+
451 => 'Unavailable For Legal Reasons',
|
|
601
556
|
500 => 'Internal Server Error',
|
|
602
557
|
501 => 'Not Implemented',
|
|
603
558
|
502 => 'Bad Gateway',
|
|
@@ -607,8 +562,6 @@ module Rack
|
|
|
607
562
|
506 => 'Variant Also Negotiates',
|
|
608
563
|
507 => 'Insufficient Storage',
|
|
609
564
|
508 => 'Loop Detected',
|
|
610
|
-
509 => 'Bandwidth Limit Exceeded',
|
|
611
|
-
510 => 'Not Extended',
|
|
612
565
|
511 => 'Network Authentication Required'
|
|
613
566
|
}
|
|
614
567
|
|
|
@@ -616,12 +569,36 @@ module Rack
|
|
|
616
569
|
STATUS_WITH_NO_ENTITY_BODY = Hash[((100..199).to_a << 204 << 304).product([true])]
|
|
617
570
|
|
|
618
571
|
SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map { |code, message|
|
|
619
|
-
[message.downcase.gsub(/\s
|
|
572
|
+
[message.downcase.gsub(/\s|-/, '_').to_sym, code]
|
|
620
573
|
}.flatten]
|
|
621
574
|
|
|
575
|
+
OBSOLETE_SYMBOLS_TO_STATUS_CODES = {
|
|
576
|
+
payload_too_large: 413,
|
|
577
|
+
unprocessable_entity: 422,
|
|
578
|
+
bandwidth_limit_exceeded: 509,
|
|
579
|
+
not_extended: 510
|
|
580
|
+
}.freeze
|
|
581
|
+
private_constant :OBSOLETE_SYMBOLS_TO_STATUS_CODES
|
|
582
|
+
|
|
583
|
+
OBSOLETE_SYMBOL_MAPPINGS = {
|
|
584
|
+
payload_too_large: :content_too_large,
|
|
585
|
+
unprocessable_entity: :unprocessable_content
|
|
586
|
+
}.freeze
|
|
587
|
+
private_constant :OBSOLETE_SYMBOL_MAPPINGS
|
|
588
|
+
|
|
622
589
|
def status_code(status)
|
|
623
590
|
if status.is_a?(Symbol)
|
|
624
|
-
SYMBOL_TO_STATUS_CODE.fetch(status)
|
|
591
|
+
SYMBOL_TO_STATUS_CODE.fetch(status) do
|
|
592
|
+
fallback_code = OBSOLETE_SYMBOLS_TO_STATUS_CODES.fetch(status) { raise ArgumentError, "Unrecognized status code #{status.inspect}" }
|
|
593
|
+
message = "Status code #{status.inspect} is deprecated and will be removed in a future version of Rack."
|
|
594
|
+
if canonical_symbol = OBSOLETE_SYMBOL_MAPPINGS[status]
|
|
595
|
+
# message = "#{message} Please use #{canonical_symbol.inspect} instead."
|
|
596
|
+
# For now, let's not emit any warning when there is a mapping.
|
|
597
|
+
else
|
|
598
|
+
warn message, uplevel: 3
|
|
599
|
+
end
|
|
600
|
+
fallback_code
|
|
601
|
+
end
|
|
625
602
|
else
|
|
626
603
|
status.to_i
|
|
627
604
|
end
|
data/lib/rack/version.rb
CHANGED
|
@@ -12,20 +12,7 @@
|
|
|
12
12
|
# so it should be enough just to <tt>require 'rack'</tt> in your code.
|
|
13
13
|
|
|
14
14
|
module Rack
|
|
15
|
-
|
|
16
|
-
VERSION = [1, 3].freeze
|
|
17
|
-
deprecate_constant :VERSION
|
|
18
|
-
|
|
19
|
-
VERSION_STRING = "1.3".freeze
|
|
20
|
-
deprecate_constant :VERSION_STRING
|
|
21
|
-
|
|
22
|
-
# The Rack protocol version number implemented.
|
|
23
|
-
def self.version
|
|
24
|
-
warn "Rack.version is deprecated and will be removed in Rack 3.1!", uplevel: 1
|
|
25
|
-
VERSION
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
RELEASE = "3.0.8"
|
|
15
|
+
RELEASE = "3.1.13"
|
|
29
16
|
|
|
30
17
|
# Return the Rack release as a dotted string.
|
|
31
18
|
def self.release
|
data/lib/rack.rb
CHANGED
|
@@ -15,23 +15,21 @@ require_relative 'rack/version'
|
|
|
15
15
|
require_relative 'rack/constants'
|
|
16
16
|
|
|
17
17
|
module Rack
|
|
18
|
-
autoload :
|
|
18
|
+
autoload :BadRequest, "rack/bad_request"
|
|
19
19
|
autoload :BodyProxy, "rack/body_proxy"
|
|
20
|
+
autoload :Builder, "rack/builder"
|
|
20
21
|
autoload :Cascade, "rack/cascade"
|
|
21
|
-
autoload :Chunked, "rack/chunked"
|
|
22
22
|
autoload :CommonLogger, "rack/common_logger"
|
|
23
23
|
autoload :ConditionalGet, "rack/conditional_get"
|
|
24
24
|
autoload :Config, "rack/config"
|
|
25
25
|
autoload :ContentLength, "rack/content_length"
|
|
26
26
|
autoload :ContentType, "rack/content_type"
|
|
27
|
+
autoload :Deflater, "rack/deflater"
|
|
28
|
+
autoload :Directory, "rack/directory"
|
|
27
29
|
autoload :ETag, "rack/etag"
|
|
28
30
|
autoload :Events, "rack/events"
|
|
29
|
-
autoload :File, "rack/file"
|
|
30
31
|
autoload :Files, "rack/files"
|
|
31
|
-
autoload :Deflater, "rack/deflater"
|
|
32
|
-
autoload :Directory, "rack/directory"
|
|
33
32
|
autoload :ForwardRequest, "rack/recursive"
|
|
34
|
-
autoload :Handler, "rack/handler"
|
|
35
33
|
autoload :Head, "rack/head"
|
|
36
34
|
autoload :Headers, "rack/headers"
|
|
37
35
|
autoload :Lint, "rack/lint"
|
|
@@ -40,32 +38,28 @@ module Rack
|
|
|
40
38
|
autoload :MediaType, "rack/media_type"
|
|
41
39
|
autoload :MethodOverride, "rack/method_override"
|
|
42
40
|
autoload :Mime, "rack/mime"
|
|
41
|
+
autoload :MockRequest, "rack/mock_request"
|
|
42
|
+
autoload :MockResponse, "rack/mock_response"
|
|
43
|
+
autoload :Multipart, "rack/multipart"
|
|
43
44
|
autoload :NullLogger, "rack/null_logger"
|
|
44
45
|
autoload :QueryParser, "rack/query_parser"
|
|
45
46
|
autoload :Recursive, "rack/recursive"
|
|
46
47
|
autoload :Reloader, "rack/reloader"
|
|
48
|
+
autoload :Request, "rack/request"
|
|
49
|
+
autoload :Response, "rack/response"
|
|
47
50
|
autoload :RewindableInput, "rack/rewindable_input"
|
|
48
51
|
autoload :Runtime, "rack/runtime"
|
|
49
52
|
autoload :Sendfile, "rack/sendfile"
|
|
50
|
-
autoload :Server, "rack/server"
|
|
51
53
|
autoload :ShowExceptions, "rack/show_exceptions"
|
|
52
54
|
autoload :ShowStatus, "rack/show_status"
|
|
53
55
|
autoload :Static, "rack/static"
|
|
54
56
|
autoload :TempfileReaper, "rack/tempfile_reaper"
|
|
55
57
|
autoload :URLMap, "rack/urlmap"
|
|
56
58
|
autoload :Utils, "rack/utils"
|
|
57
|
-
autoload :Multipart, "rack/multipart"
|
|
58
|
-
|
|
59
|
-
autoload :MockRequest, "rack/mock_request"
|
|
60
|
-
autoload :MockResponse, "rack/mock_response"
|
|
61
|
-
|
|
62
|
-
autoload :Request, "rack/request"
|
|
63
|
-
autoload :Response, "rack/response"
|
|
64
59
|
|
|
65
60
|
module Auth
|
|
66
61
|
autoload :Basic, "rack/auth/basic"
|
|
67
|
-
autoload :AbstractRequest, "rack/auth/abstract/request"
|
|
68
62
|
autoload :AbstractHandler, "rack/auth/abstract/handler"
|
|
69
|
-
autoload :
|
|
63
|
+
autoload :AbstractRequest, "rack/auth/abstract/request"
|
|
70
64
|
end
|
|
71
65
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rack
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.1.13
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Leah Neukirchen
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 2025-04-13 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: minitest
|
|
@@ -89,15 +88,10 @@ files:
|
|
|
89
88
|
- lib/rack/auth/abstract/handler.rb
|
|
90
89
|
- lib/rack/auth/abstract/request.rb
|
|
91
90
|
- lib/rack/auth/basic.rb
|
|
92
|
-
- lib/rack/
|
|
93
|
-
- lib/rack/auth/digest/md5.rb
|
|
94
|
-
- lib/rack/auth/digest/nonce.rb
|
|
95
|
-
- lib/rack/auth/digest/params.rb
|
|
96
|
-
- lib/rack/auth/digest/request.rb
|
|
91
|
+
- lib/rack/bad_request.rb
|
|
97
92
|
- lib/rack/body_proxy.rb
|
|
98
93
|
- lib/rack/builder.rb
|
|
99
94
|
- lib/rack/cascade.rb
|
|
100
|
-
- lib/rack/chunked.rb
|
|
101
95
|
- lib/rack/common_logger.rb
|
|
102
96
|
- lib/rack/conditional_get.rb
|
|
103
97
|
- lib/rack/config.rb
|
|
@@ -108,7 +102,6 @@ files:
|
|
|
108
102
|
- lib/rack/directory.rb
|
|
109
103
|
- lib/rack/etag.rb
|
|
110
104
|
- lib/rack/events.rb
|
|
111
|
-
- lib/rack/file.rb
|
|
112
105
|
- lib/rack/files.rb
|
|
113
106
|
- lib/rack/head.rb
|
|
114
107
|
- lib/rack/headers.rb
|
|
@@ -149,7 +142,6 @@ metadata:
|
|
|
149
142
|
changelog_uri: https://github.com/rack/rack/blob/main/CHANGELOG.md
|
|
150
143
|
documentation_uri: https://rubydoc.info/github/rack/rack
|
|
151
144
|
source_code_uri: https://github.com/rack/rack
|
|
152
|
-
post_install_message:
|
|
153
145
|
rdoc_options: []
|
|
154
146
|
require_paths:
|
|
155
147
|
- lib
|
|
@@ -164,8 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
164
156
|
- !ruby/object:Gem::Version
|
|
165
157
|
version: '0'
|
|
166
158
|
requirements: []
|
|
167
|
-
rubygems_version: 3.
|
|
168
|
-
signing_key:
|
|
159
|
+
rubygems_version: 3.6.2
|
|
169
160
|
specification_version: 4
|
|
170
161
|
summary: A modular Ruby webserver interface.
|
|
171
162
|
test_files: []
|
data/lib/rack/auth/digest/md5.rb
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
require_relative '../digest'
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
require_relative '../digest'
|