rack 3.0.5 → 3.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +383 -1
- data/CONTRIBUTING.md +11 -9
- data/README.md +95 -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/body_proxy.rb +18 -2
- data/lib/rack/builder.rb +29 -10
- data/lib/rack/cascade.rb +0 -3
- data/lib/rack/common_logger.rb +3 -2
- data/lib/rack/conditional_get.rb +4 -3
- data/lib/rack/constants.rb +3 -1
- data/lib/rack/etag.rb +3 -0
- 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 +18 -9
- data/lib/rack/mime.rb +6 -5
- data/lib/rack/mock_request.rb +10 -15
- data/lib/rack/mock_response.rb +39 -18
- data/lib/rack/multipart/parser.rb +169 -73
- data/lib/rack/multipart/uploaded_file.rb +42 -5
- data/lib/rack/multipart.rb +9 -1
- data/lib/rack/query_parser.rb +86 -97
- data/lib/rack/request.rb +67 -100
- data/lib/rack/response.rb +29 -19
- data/lib/rack/rewindable_input.rb +4 -1
- data/lib/rack/sendfile.rb +2 -2
- data/lib/rack/show_exceptions.rb +10 -4
- data/lib/rack/show_status.rb +0 -2
- data/lib/rack/static.rb +2 -1
- data/lib/rack/utils.rb +78 -110
- data/lib/rack/version.rb +3 -20
- data/lib/rack.rb +11 -17
- metadata +6 -15
- 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/builder.rb
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'urlmap'
|
|
4
4
|
|
|
5
|
+
module Rack; end
|
|
6
|
+
Rack::BUILDER_TOPLEVEL_BINDING = ->(builder){builder.instance_eval{binding}}
|
|
7
|
+
|
|
5
8
|
module Rack
|
|
6
9
|
# Rack::Builder provides a domain-specific language (DSL) to construct Rack
|
|
7
10
|
# applications. It is primarily used to parse +config.ru+ files which
|
|
@@ -53,15 +56,15 @@ module Rack
|
|
|
53
56
|
# Rack::Builder.parse_file('app.rb')
|
|
54
57
|
# # requires app.rb, which can be anywhere in Ruby's
|
|
55
58
|
# # load path. After requiring, assumes App constant
|
|
56
|
-
# #
|
|
59
|
+
# # is a Rack application
|
|
57
60
|
#
|
|
58
61
|
# Rack::Builder.parse_file('./my_app.rb')
|
|
59
62
|
# # requires ./my_app.rb, which should be in the
|
|
60
63
|
# # process's current directory. After requiring,
|
|
61
|
-
# # assumes MyApp constant
|
|
62
|
-
def self.parse_file(path)
|
|
64
|
+
# # assumes MyApp constant is a Rack application
|
|
65
|
+
def self.parse_file(path, **options)
|
|
63
66
|
if path.end_with?('.ru')
|
|
64
|
-
return self.load_file(path)
|
|
67
|
+
return self.load_file(path, **options)
|
|
65
68
|
else
|
|
66
69
|
require path
|
|
67
70
|
return Object.const_get(::File.basename(path, '.rb').split('_').map(&:capitalize).join(''))
|
|
@@ -81,7 +84,7 @@ module Rack
|
|
|
81
84
|
# use Rack::ContentLength
|
|
82
85
|
# require './app.rb'
|
|
83
86
|
# run App
|
|
84
|
-
def self.load_file(path)
|
|
87
|
+
def self.load_file(path, **options)
|
|
85
88
|
config = ::File.read(path)
|
|
86
89
|
config.slice!(/\A#{UTF_8_BOM}/) if config.encoding == Encoding::UTF_8
|
|
87
90
|
|
|
@@ -91,16 +94,18 @@ module Rack
|
|
|
91
94
|
|
|
92
95
|
config.sub!(/^__END__\n.*\Z/m, '')
|
|
93
96
|
|
|
94
|
-
return new_from_string(config, path)
|
|
97
|
+
return new_from_string(config, path, **options)
|
|
95
98
|
end
|
|
96
99
|
|
|
97
100
|
# Evaluate the given +builder_script+ string in the context of
|
|
98
101
|
# a Rack::Builder block, returning a Rack application.
|
|
99
|
-
def self.new_from_string(builder_script,
|
|
102
|
+
def self.new_from_string(builder_script, path = "(rackup)", **options)
|
|
103
|
+
builder = self.new(**options)
|
|
104
|
+
|
|
100
105
|
# We want to build a variant of TOPLEVEL_BINDING with self as a Rack::Builder instance.
|
|
101
106
|
# We cannot use instance_eval(String) as that would resolve constants differently.
|
|
102
|
-
binding
|
|
103
|
-
eval
|
|
107
|
+
binding = BUILDER_TOPLEVEL_BINDING.call(builder)
|
|
108
|
+
eval(builder_script, binding, path)
|
|
104
109
|
|
|
105
110
|
return builder.to_app
|
|
106
111
|
end
|
|
@@ -108,16 +113,24 @@ module Rack
|
|
|
108
113
|
# Initialize a new Rack::Builder instance. +default_app+ specifies the
|
|
109
114
|
# default application if +run+ is not called later. If a block
|
|
110
115
|
# is given, it is evaluated in the context of the instance.
|
|
111
|
-
def initialize(default_app = nil, &block)
|
|
116
|
+
def initialize(default_app = nil, **options, &block)
|
|
112
117
|
@use = []
|
|
113
118
|
@map = nil
|
|
114
119
|
@run = default_app
|
|
115
120
|
@warmup = nil
|
|
116
121
|
@freeze_app = false
|
|
122
|
+
@options = options
|
|
117
123
|
|
|
118
124
|
instance_eval(&block) if block_given?
|
|
119
125
|
end
|
|
120
126
|
|
|
127
|
+
# Any options provided to the Rack::Builder instance at initialization.
|
|
128
|
+
# These options can be server-specific. Some general options are:
|
|
129
|
+
#
|
|
130
|
+
# * +:isolation+: One of +process+, +thread+ or +fiber+. The execution
|
|
131
|
+
# isolation model to use.
|
|
132
|
+
attr :options
|
|
133
|
+
|
|
121
134
|
# Create a new Rack::Builder instance and return the Rack application
|
|
122
135
|
# generated from it.
|
|
123
136
|
def self.app(default_app = nil, &block)
|
|
@@ -149,6 +162,8 @@ module Rack
|
|
|
149
162
|
@use << proc { |app| generate_map(app, mapping) }
|
|
150
163
|
end
|
|
151
164
|
@use << proc { |app| middleware.new(app, *args, &block) }
|
|
165
|
+
|
|
166
|
+
nil
|
|
152
167
|
end
|
|
153
168
|
# :nocov:
|
|
154
169
|
ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true)
|
|
@@ -181,6 +196,8 @@ module Rack
|
|
|
181
196
|
raise ArgumentError, "Both app and block given!" if app && block_given?
|
|
182
197
|
|
|
183
198
|
@run = app || block
|
|
199
|
+
|
|
200
|
+
nil
|
|
184
201
|
end
|
|
185
202
|
|
|
186
203
|
# Takes a lambda or block that is used to warm-up the application. This block is called
|
|
@@ -239,6 +256,8 @@ module Rack
|
|
|
239
256
|
def map(path, &block)
|
|
240
257
|
@map ||= {}
|
|
241
258
|
@map[path] = block
|
|
259
|
+
|
|
260
|
+
nil
|
|
242
261
|
end
|
|
243
262
|
|
|
244
263
|
# Freeze the app (set using run) and all middleware instances when building the application
|
data/lib/rack/cascade.rb
CHANGED
data/lib/rack/common_logger.rb
CHANGED
|
@@ -20,7 +20,7 @@ module Rack
|
|
|
20
20
|
# The actual format is slightly different than the above due to the
|
|
21
21
|
# separation of SCRIPT_NAME and PATH_INFO, and because the elapsed
|
|
22
22
|
# time in seconds is included at the end.
|
|
23
|
-
FORMAT = %{%s - %s [%s] "%s %s%s%s %s" %d %s %0.4f
|
|
23
|
+
FORMAT = %{%s - %s [%s] "%s %s%s%s %s" %d %s %0.4f }
|
|
24
24
|
|
|
25
25
|
# +logger+ can be any object that supports the +write+ or +<<+ methods,
|
|
26
26
|
# which includes the standard library Logger. These methods are called
|
|
@@ -66,7 +66,8 @@ module Rack
|
|
|
66
66
|
length,
|
|
67
67
|
Utils.clock_time - began_at)
|
|
68
68
|
|
|
69
|
-
msg.gsub!(/[^[:print:]
|
|
69
|
+
msg.gsub!(/[^[:print:]]/) { |c| sprintf("\\x%x", c.ord) }
|
|
70
|
+
msg[-1] = "\n"
|
|
70
71
|
|
|
71
72
|
logger = @logger || request.get_header(RACK_ERRORS)
|
|
72
73
|
# Standard library logger doesn't support write but it supports << which actually
|
data/lib/rack/conditional_get.rb
CHANGED
|
@@ -34,9 +34,10 @@ module Rack
|
|
|
34
34
|
response[0] = 304
|
|
35
35
|
headers.delete(CONTENT_TYPE)
|
|
36
36
|
headers.delete(CONTENT_LENGTH)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
|
|
38
|
+
# We are done with the body:
|
|
39
|
+
body.close if body.respond_to?(:close)
|
|
40
|
+
response[2] = []
|
|
40
41
|
end
|
|
41
42
|
response
|
|
42
43
|
else
|
data/lib/rack/constants.rb
CHANGED
|
@@ -32,6 +32,7 @@ module Rack
|
|
|
32
32
|
DELETE = 'DELETE'
|
|
33
33
|
HEAD = 'HEAD'
|
|
34
34
|
OPTIONS = 'OPTIONS'
|
|
35
|
+
CONNECT = 'CONNECT'
|
|
35
36
|
LINK = 'LINK'
|
|
36
37
|
UNLINK = 'UNLINK'
|
|
37
38
|
TRACE = 'TRACE'
|
|
@@ -39,6 +40,7 @@ module Rack
|
|
|
39
40
|
# Rack environment variables
|
|
40
41
|
RACK_VERSION = 'rack.version'
|
|
41
42
|
RACK_TEMPFILES = 'rack.tempfiles'
|
|
43
|
+
RACK_EARLY_HINTS = 'rack.early_hints'
|
|
42
44
|
RACK_ERRORS = 'rack.errors'
|
|
43
45
|
RACK_LOGGER = 'rack.logger'
|
|
44
46
|
RACK_INPUT = 'rack.input'
|
|
@@ -52,6 +54,7 @@ module Rack
|
|
|
52
54
|
RACK_MULTIPART_BUFFER_SIZE = 'rack.multipart.buffer_size'
|
|
53
55
|
RACK_MULTIPART_TEMPFILE_FACTORY = 'rack.multipart.tempfile_factory'
|
|
54
56
|
RACK_RESPONSE_FINISHED = 'rack.response_finished'
|
|
57
|
+
RACK_PROTOCOL = 'rack.protocol'
|
|
55
58
|
RACK_REQUEST_FORM_INPUT = 'rack.request.form_input'
|
|
56
59
|
RACK_REQUEST_FORM_HASH = 'rack.request.form_hash'
|
|
57
60
|
RACK_REQUEST_FORM_PAIRS = 'rack.request.form_pairs'
|
|
@@ -60,7 +63,6 @@ module Rack
|
|
|
60
63
|
RACK_REQUEST_COOKIE_HASH = 'rack.request.cookie_hash'
|
|
61
64
|
RACK_REQUEST_COOKIE_STRING = 'rack.request.cookie_string'
|
|
62
65
|
RACK_REQUEST_QUERY_HASH = 'rack.request.query_hash'
|
|
63
|
-
RACK_REQUEST_QUERY_PAIRS = 'rack.request.query_pairs'
|
|
64
66
|
RACK_REQUEST_QUERY_STRING = 'rack.request.query_string'
|
|
65
67
|
RACK_METHODOVERRIDE_ORIGINAL_METHOD = 'rack.methodoverride.original_method'
|
|
66
68
|
end
|
data/lib/rack/etag.rb
CHANGED
data/lib/rack/head.rb
CHANGED
|
@@ -15,9 +15,8 @@ module Rack
|
|
|
15
15
|
_, _, body = response = @app.call(env)
|
|
16
16
|
|
|
17
17
|
if env[REQUEST_METHOD] == HEAD
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
end
|
|
18
|
+
body.close if body.respond_to?(:close)
|
|
19
|
+
response[2] = []
|
|
21
20
|
end
|
|
22
21
|
|
|
23
22
|
response
|
data/lib/rack/headers.rb
CHANGED
|
@@ -1,9 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Rack
|
|
2
4
|
# Rack::Headers is a Hash subclass that downcases all keys. It's designed
|
|
3
5
|
# to be used by rack applications that don't implement the Rack 3 SPEC
|
|
4
6
|
# (by using non-lowercase response header keys), automatically handling
|
|
5
7
|
# the downcasing of keys.
|
|
6
8
|
class Headers < Hash
|
|
9
|
+
KNOWN_HEADERS = {}
|
|
10
|
+
%w(
|
|
11
|
+
Accept-CH
|
|
12
|
+
Accept-Patch
|
|
13
|
+
Accept-Ranges
|
|
14
|
+
Access-Control-Allow-Credentials
|
|
15
|
+
Access-Control-Allow-Headers
|
|
16
|
+
Access-Control-Allow-Methods
|
|
17
|
+
Access-Control-Allow-Origin
|
|
18
|
+
Access-Control-Expose-Headers
|
|
19
|
+
Access-Control-Max-Age
|
|
20
|
+
Age
|
|
21
|
+
Allow
|
|
22
|
+
Alt-Svc
|
|
23
|
+
Cache-Control
|
|
24
|
+
Connection
|
|
25
|
+
Content-Disposition
|
|
26
|
+
Content-Encoding
|
|
27
|
+
Content-Language
|
|
28
|
+
Content-Length
|
|
29
|
+
Content-Location
|
|
30
|
+
Content-MD5
|
|
31
|
+
Content-Range
|
|
32
|
+
Content-Security-Policy
|
|
33
|
+
Content-Security-Policy-Report-Only
|
|
34
|
+
Content-Type
|
|
35
|
+
Date
|
|
36
|
+
Delta-Base
|
|
37
|
+
ETag
|
|
38
|
+
Expect-CT
|
|
39
|
+
Expires
|
|
40
|
+
Feature-Policy
|
|
41
|
+
IM
|
|
42
|
+
Last-Modified
|
|
43
|
+
Link
|
|
44
|
+
Location
|
|
45
|
+
NEL
|
|
46
|
+
P3P
|
|
47
|
+
Permissions-Policy
|
|
48
|
+
Pragma
|
|
49
|
+
Preference-Applied
|
|
50
|
+
Proxy-Authenticate
|
|
51
|
+
Public-Key-Pins
|
|
52
|
+
Referrer-Policy
|
|
53
|
+
Refresh
|
|
54
|
+
Report-To
|
|
55
|
+
Retry-After
|
|
56
|
+
Server
|
|
57
|
+
Set-Cookie
|
|
58
|
+
Status
|
|
59
|
+
Strict-Transport-Security
|
|
60
|
+
Timing-Allow-Origin
|
|
61
|
+
Tk
|
|
62
|
+
Trailer
|
|
63
|
+
Transfer-Encoding
|
|
64
|
+
Upgrade
|
|
65
|
+
Vary
|
|
66
|
+
Via
|
|
67
|
+
WWW-Authenticate
|
|
68
|
+
Warning
|
|
69
|
+
X-Cascade
|
|
70
|
+
X-Content-Duration
|
|
71
|
+
X-Content-Security-Policy
|
|
72
|
+
X-Content-Type-Options
|
|
73
|
+
X-Correlation-ID
|
|
74
|
+
X-Correlation-Id
|
|
75
|
+
X-Download-Options
|
|
76
|
+
X-Frame-Options
|
|
77
|
+
X-Permitted-Cross-Domain-Policies
|
|
78
|
+
X-Powered-By
|
|
79
|
+
X-Redirect-By
|
|
80
|
+
X-Request-ID
|
|
81
|
+
X-Request-Id
|
|
82
|
+
X-Runtime
|
|
83
|
+
X-UA-Compatible
|
|
84
|
+
X-WebKit-CS
|
|
85
|
+
X-XSS-Protection
|
|
86
|
+
).each do |str|
|
|
87
|
+
downcased = str.downcase.freeze
|
|
88
|
+
KNOWN_HEADERS[str] = KNOWN_HEADERS[downcased] = downcased
|
|
89
|
+
end
|
|
90
|
+
|
|
7
91
|
def self.[](*items)
|
|
8
92
|
if items.length % 2 != 0
|
|
9
93
|
if items.length == 1 && items.first.is_a?(Hash)
|
|
@@ -28,7 +112,7 @@ module Rack
|
|
|
28
112
|
end
|
|
29
113
|
|
|
30
114
|
def []=(key, value)
|
|
31
|
-
super(key.downcase.freeze, value)
|
|
115
|
+
super(KNOWN_HEADERS[key] || key.downcase.freeze, value)
|
|
32
116
|
end
|
|
33
117
|
alias store []=
|
|
34
118
|
|
|
@@ -148,7 +232,7 @@ module Rack
|
|
|
148
232
|
private
|
|
149
233
|
|
|
150
234
|
def downcase_key(key)
|
|
151
|
-
key.is_a?(String) ? key.downcase : key
|
|
235
|
+
key.is_a?(String) ? KNOWN_HEADERS[key] || key.downcase : key
|
|
152
236
|
end
|
|
153
237
|
end
|
|
154
238
|
end
|