rack 3.0.15 → 3.2.6
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +368 -6
- data/CONTRIBUTING.md +11 -9
- data/README.md +103 -28
- data/SPEC.rdoc +206 -288
- data/lib/rack/auth/abstract/request.rb +2 -0
- data/lib/rack/auth/basic.rb +1 -2
- data/lib/rack/bad_request.rb +8 -0
- data/lib/rack/builder.rb +29 -10
- data/lib/rack/cascade.rb +0 -3
- data/lib/rack/conditional_get.rb +4 -3
- data/lib/rack/constants.rb +4 -0
- data/lib/rack/directory.rb +6 -3
- data/lib/rack/events.rb +21 -6
- data/lib/rack/files.rb +1 -1
- data/lib/rack/head.rb +2 -3
- data/lib/rack/headers.rb +86 -2
- data/lib/rack/lint.rb +482 -425
- data/lib/rack/media_type.rb +14 -10
- data/lib/rack/mime.rb +6 -5
- data/lib/rack/mock_request.rb +10 -15
- data/lib/rack/mock_response.rb +50 -20
- data/lib/rack/multipart/parser.rb +255 -76
- data/lib/rack/multipart/uploaded_file.rb +42 -5
- data/lib/rack/multipart.rb +34 -1
- data/lib/rack/query_parser.rb +86 -78
- data/lib/rack/request.rb +78 -65
- data/lib/rack/response.rb +28 -20
- data/lib/rack/rewindable_input.rb +4 -1
- data/lib/rack/sendfile.rb +51 -21
- data/lib/rack/show_exceptions.rb +10 -4
- data/lib/rack/show_status.rb +0 -2
- data/lib/rack/static.rb +7 -3
- data/lib/rack/utils.rb +175 -119
- data/lib/rack/version.rb +3 -20
- data/lib/rack.rb +1 -4
- metadata +6 -12
- 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/logger.rb +0 -22
data/lib/rack/media_type.rb
CHANGED
|
@@ -14,12 +14,11 @@ module Rack
|
|
|
14
14
|
# For more information on the use of media types in HTTP, see:
|
|
15
15
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
|
|
16
16
|
def type(content_type)
|
|
17
|
-
return nil unless content_type
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
end
|
|
17
|
+
return nil unless content_type && !content_type.empty?
|
|
18
|
+
type = content_type.split(SPLIT_PATTERN, 2).first
|
|
19
|
+
type.rstrip!
|
|
20
|
+
type.downcase!
|
|
21
|
+
type
|
|
23
22
|
end
|
|
24
23
|
|
|
25
24
|
# The media type parameters provided in CONTENT_TYPE as a Hash, or
|
|
@@ -27,8 +26,13 @@ module Rack
|
|
|
27
26
|
# provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8",
|
|
28
27
|
# this method responds with the following Hash:
|
|
29
28
|
# { 'charset' => 'utf-8' }
|
|
29
|
+
#
|
|
30
|
+
# This will pass back parameters with empty strings in the hash if they
|
|
31
|
+
# lack a value (e.g., "text/plain;charset=" will return { 'charset' => '' },
|
|
32
|
+
# and "text/plain;charset" will return { 'charset' => '' }, similarly to
|
|
33
|
+
# the query params parser (barring the latter case, which returns nil instead)).
|
|
30
34
|
def params(content_type)
|
|
31
|
-
return {} if content_type.nil?
|
|
35
|
+
return {} if content_type.nil? || content_type.empty?
|
|
32
36
|
|
|
33
37
|
content_type.split(SPLIT_PATTERN)[1..-1].each_with_object({}) do |s, hsh|
|
|
34
38
|
s.strip!
|
|
@@ -40,9 +44,9 @@ module Rack
|
|
|
40
44
|
|
|
41
45
|
private
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
def strip_doublequotes(str)
|
|
48
|
+
(str && str.start_with?('"') && str.end_with?('"')) ? str[1..-2] : str || ''
|
|
49
|
+
end
|
|
46
50
|
end
|
|
47
51
|
end
|
|
48
52
|
end
|
data/lib/rack/mime.rb
CHANGED
|
@@ -290,7 +290,7 @@ module Rack
|
|
|
290
290
|
".jpg" => "image/jpeg",
|
|
291
291
|
".jpgv" => "video/jpeg",
|
|
292
292
|
".jpm" => "video/jpm",
|
|
293
|
-
".js" => "
|
|
293
|
+
".js" => "text/javascript",
|
|
294
294
|
".json" => "application/json",
|
|
295
295
|
".karbon" => "application/vnd.kde.karbon",
|
|
296
296
|
".kfo" => "application/vnd.kde.kformula",
|
|
@@ -338,6 +338,7 @@ module Rack
|
|
|
338
338
|
".mif" => "application/vnd.mif",
|
|
339
339
|
".mime" => "message/rfc822",
|
|
340
340
|
".mj2" => "video/mj2",
|
|
341
|
+
".mjs" => "text/javascript",
|
|
341
342
|
".mlp" => "application/vnd.dolby.mlp",
|
|
342
343
|
".mmd" => "application/vnd.chipnuts.karaoke-mmd",
|
|
343
344
|
".mmf" => "application/vnd.smaf",
|
|
@@ -409,7 +410,7 @@ module Rack
|
|
|
409
410
|
".ogx" => "application/ogg",
|
|
410
411
|
".org" => "application/vnd.lotus-organizer",
|
|
411
412
|
".otc" => "application/vnd.oasis.opendocument.chart-template",
|
|
412
|
-
".otf" => "
|
|
413
|
+
".otf" => "font/otf",
|
|
413
414
|
".otg" => "application/vnd.oasis.opendocument.graphics-template",
|
|
414
415
|
".oth" => "application/vnd.oasis.opendocument.text-web",
|
|
415
416
|
".oti" => "application/vnd.oasis.opendocument.image-template",
|
|
@@ -590,7 +591,7 @@ module Rack
|
|
|
590
591
|
".trm" => "application/x-msterminal",
|
|
591
592
|
".ts" => "video/mp2t",
|
|
592
593
|
".tsv" => "text/tab-separated-values",
|
|
593
|
-
".ttf" => "
|
|
594
|
+
".ttf" => "font/ttf",
|
|
594
595
|
".twd" => "application/vnd.simtech-mindmapper",
|
|
595
596
|
".txd" => "application/vnd.genomatix.tuxedo",
|
|
596
597
|
".txf" => "application/vnd.mobius.txf",
|
|
@@ -636,8 +637,8 @@ module Rack
|
|
|
636
637
|
".wmv" => "video/x-ms-wmv",
|
|
637
638
|
".wmx" => "video/x-ms-wmx",
|
|
638
639
|
".wmz" => "application/x-ms-wmz",
|
|
639
|
-
".woff" => "
|
|
640
|
-
".woff2" => "
|
|
640
|
+
".woff" => "font/woff",
|
|
641
|
+
".woff2" => "font/woff2",
|
|
641
642
|
".wpd" => "application/vnd.wordperfect",
|
|
642
643
|
".wpl" => "application/vnd.ms-wpl",
|
|
643
644
|
".wps" => "application/vnd.ms-works",
|
data/lib/rack/mock_request.rb
CHANGED
|
@@ -41,11 +41,6 @@ module Rack
|
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
DEFAULT_ENV = {
|
|
45
|
-
RACK_INPUT => StringIO.new,
|
|
46
|
-
RACK_ERRORS => StringIO.new,
|
|
47
|
-
}.freeze
|
|
48
|
-
|
|
49
44
|
def initialize(app)
|
|
50
45
|
@app = app
|
|
51
46
|
end
|
|
@@ -104,7 +99,7 @@ module Rack
|
|
|
104
99
|
uri = parse_uri_rfc2396(uri)
|
|
105
100
|
uri.path = "/#{uri.path}" unless uri.path[0] == ?/
|
|
106
101
|
|
|
107
|
-
env =
|
|
102
|
+
env = {}
|
|
108
103
|
|
|
109
104
|
env[REQUEST_METHOD] = (opts[:method] ? opts[:method].to_s.upcase : GET).b
|
|
110
105
|
env[SERVER_NAME] = (uri.host || "example.org").b
|
|
@@ -144,20 +139,20 @@ module Rack
|
|
|
144
139
|
end
|
|
145
140
|
end
|
|
146
141
|
|
|
147
|
-
opts[:input]
|
|
148
|
-
if String ===
|
|
149
|
-
rack_input = StringIO.new(
|
|
150
|
-
else
|
|
151
|
-
rack_input = opts[:input]
|
|
142
|
+
rack_input = opts[:input]
|
|
143
|
+
if String === rack_input
|
|
144
|
+
rack_input = StringIO.new(rack_input)
|
|
152
145
|
end
|
|
153
146
|
|
|
154
|
-
rack_input
|
|
155
|
-
|
|
147
|
+
if rack_input
|
|
148
|
+
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
|
|
149
|
+
env[RACK_INPUT] = rack_input
|
|
156
150
|
|
|
157
|
-
|
|
151
|
+
env["CONTENT_LENGTH"] ||= env[RACK_INPUT].size.to_s if env[RACK_INPUT].respond_to?(:size)
|
|
152
|
+
end
|
|
158
153
|
|
|
159
154
|
opts.each { |field, value|
|
|
160
|
-
env[field] = value
|
|
155
|
+
env[field] = value if String === field
|
|
161
156
|
}
|
|
162
157
|
|
|
163
158
|
env
|
data/lib/rack/mock_response.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require '
|
|
3
|
+
require 'stringio'
|
|
4
4
|
require 'time'
|
|
5
5
|
|
|
6
6
|
require_relative 'response'
|
|
@@ -11,6 +11,30 @@ module Rack
|
|
|
11
11
|
# MockRequest.
|
|
12
12
|
|
|
13
13
|
class MockResponse < Rack::Response
|
|
14
|
+
class Cookie
|
|
15
|
+
attr_reader :name, :value, :path, :domain, :expires, :secure
|
|
16
|
+
|
|
17
|
+
def initialize(args)
|
|
18
|
+
@name = args["name"]
|
|
19
|
+
@value = args["value"]
|
|
20
|
+
@path = args["path"]
|
|
21
|
+
@domain = args["domain"]
|
|
22
|
+
@expires = args["expires"]
|
|
23
|
+
@secure = args["secure"]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def method_missing(method_name, *args, &block)
|
|
27
|
+
@value.send(method_name, *args, &block)
|
|
28
|
+
end
|
|
29
|
+
# :nocov:
|
|
30
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
|
31
|
+
# :nocov:
|
|
32
|
+
|
|
33
|
+
def respond_to_missing?(method_name, include_all = false)
|
|
34
|
+
@value.respond_to?(method_name, include_all) || super
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
14
38
|
class << self
|
|
15
39
|
alias [] new
|
|
16
40
|
end
|
|
@@ -59,8 +83,16 @@ module Rack
|
|
|
59
83
|
# end
|
|
60
84
|
buffer = @buffered_body = String.new
|
|
61
85
|
|
|
62
|
-
|
|
63
|
-
|
|
86
|
+
begin
|
|
87
|
+
if @body.respond_to?(:each)
|
|
88
|
+
@body.each do |chunk|
|
|
89
|
+
buffer << chunk
|
|
90
|
+
end
|
|
91
|
+
else
|
|
92
|
+
@body.call(StringIO.new(buffer))
|
|
93
|
+
end
|
|
94
|
+
ensure
|
|
95
|
+
@body.close if @body.respond_to?(:close)
|
|
64
96
|
end
|
|
65
97
|
|
|
66
98
|
return buffer
|
|
@@ -78,22 +110,20 @@ module Rack
|
|
|
78
110
|
|
|
79
111
|
def parse_cookies_from_header
|
|
80
112
|
cookies = Hash.new
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
Array(set_cookie_header).each do |
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
cookies.store(cookie_name, parsed_cookie)
|
|
96
|
-
end
|
|
113
|
+
set_cookie_header = headers['set-cookie']
|
|
114
|
+
if set_cookie_header && !set_cookie_header.empty?
|
|
115
|
+
Array(set_cookie_header).each do |cookie|
|
|
116
|
+
cookie_name, cookie_filling = cookie.split('=', 2)
|
|
117
|
+
cookie_attributes = identify_cookie_attributes cookie_filling
|
|
118
|
+
parsed_cookie = Cookie.new(
|
|
119
|
+
'name' => cookie_name.strip,
|
|
120
|
+
'value' => cookie_attributes.fetch('value'),
|
|
121
|
+
'path' => cookie_attributes.fetch('path', nil),
|
|
122
|
+
'domain' => cookie_attributes.fetch('domain', nil),
|
|
123
|
+
'expires' => cookie_attributes.fetch('expires', nil),
|
|
124
|
+
'secure' => cookie_attributes.fetch('secure', false)
|
|
125
|
+
)
|
|
126
|
+
cookies.store(cookie_name, parsed_cookie)
|
|
97
127
|
end
|
|
98
128
|
end
|
|
99
129
|
cookies
|
|
@@ -102,7 +132,7 @@ module Rack
|
|
|
102
132
|
def identify_cookie_attributes(cookie_filling)
|
|
103
133
|
cookie_bits = cookie_filling.split(';')
|
|
104
134
|
cookie_attributes = Hash.new
|
|
105
|
-
cookie_attributes.store('value', cookie_bits[0].strip)
|
|
135
|
+
cookie_attributes.store('value', Array(cookie_bits[0].strip))
|
|
106
136
|
cookie_bits.drop(1).each do |bit|
|
|
107
137
|
if bit.include? '='
|
|
108
138
|
cookie_attribute, attribute_value = bit.split('=', 2)
|