rack 2.0.8 → 2.2.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +690 -0
- data/CONTRIBUTING.md +136 -0
- data/{COPYING → MIT-LICENSE} +4 -2
- data/README.rdoc +152 -148
- data/Rakefile +37 -23
- data/{SPEC → SPEC.rdoc} +29 -5
- data/bin/rackup +1 -0
- data/example/lobster.ru +2 -0
- data/example/protectedlobster.rb +3 -1
- data/example/protectedlobster.ru +2 -0
- data/lib/rack.rb +67 -73
- data/lib/rack/auth/abstract/handler.rb +3 -1
- data/lib/rack/auth/abstract/request.rb +1 -1
- data/lib/rack/auth/basic.rb +7 -4
- data/lib/rack/auth/digest/md5.rb +13 -11
- data/lib/rack/auth/digest/nonce.rb +6 -3
- data/lib/rack/auth/digest/params.rb +4 -2
- data/lib/rack/auth/digest/request.rb +5 -3
- data/lib/rack/body_proxy.rb +15 -14
- data/lib/rack/builder.rb +116 -23
- data/lib/rack/cascade.rb +28 -12
- data/lib/rack/chunked.rb +68 -20
- data/lib/rack/common_logger.rb +33 -25
- data/lib/rack/conditional_get.rb +20 -16
- data/lib/rack/config.rb +2 -0
- data/lib/rack/content_length.rb +8 -7
- data/lib/rack/content_type.rb +5 -4
- data/lib/rack/core_ext/regexp.rb +14 -0
- data/lib/rack/deflater.rb +59 -34
- data/lib/rack/directory.rb +84 -64
- data/lib/rack/etag.rb +5 -4
- data/lib/rack/events.rb +19 -20
- data/lib/rack/file.rb +4 -173
- data/lib/rack/files.rb +218 -0
- data/lib/rack/handler.rb +7 -2
- data/lib/rack/handler/cgi.rb +2 -3
- data/lib/rack/handler/fastcgi.rb +4 -4
- data/lib/rack/handler/lsws.rb +3 -3
- data/lib/rack/handler/scgi.rb +9 -8
- data/lib/rack/handler/thin.rb +3 -3
- data/lib/rack/handler/webrick.rb +15 -6
- data/lib/rack/head.rb +1 -1
- data/lib/rack/lint.rb +71 -25
- data/lib/rack/lobster.rb +10 -10
- data/lib/rack/lock.rb +2 -1
- data/lib/rack/logger.rb +2 -0
- data/lib/rack/media_type.rb +10 -5
- data/lib/rack/method_override.rb +4 -2
- data/lib/rack/mime.rb +9 -1
- data/lib/rack/mock.rb +97 -20
- data/lib/rack/multipart.rb +6 -4
- data/lib/rack/multipart/generator.rb +17 -13
- data/lib/rack/multipart/parser.rb +54 -56
- data/lib/rack/multipart/uploaded_file.rb +15 -7
- data/lib/rack/null_logger.rb +2 -0
- data/lib/rack/query_parser.rb +53 -28
- data/lib/rack/recursive.rb +7 -5
- data/lib/rack/reloader.rb +8 -4
- data/lib/rack/request.rb +220 -61
- data/lib/rack/response.rb +127 -44
- data/lib/rack/rewindable_input.rb +4 -3
- data/lib/rack/runtime.rb +6 -4
- data/lib/rack/sendfile.rb +13 -9
- data/lib/rack/server.rb +95 -24
- data/lib/rack/session/abstract/id.rb +36 -23
- data/lib/rack/session/cookie.rb +11 -12
- data/lib/rack/session/memcache.rb +4 -93
- data/lib/rack/session/pool.rb +5 -3
- data/lib/rack/show_exceptions.rb +21 -17
- data/lib/rack/show_status.rb +9 -9
- data/lib/rack/static.rb +23 -11
- data/lib/rack/tempfile_reaper.rb +1 -1
- data/lib/rack/urlmap.rb +12 -6
- data/lib/rack/utils.rb +98 -109
- data/lib/rack/version.rb +29 -0
- data/rack.gemspec +40 -28
- metadata +36 -177
- data/HISTORY.md +0 -505
- data/test/builder/an_underscore_app.rb +0 -5
- data/test/builder/anything.rb +0 -5
- data/test/builder/comment.ru +0 -4
- data/test/builder/end.ru +0 -5
- data/test/builder/line.ru +0 -1
- data/test/builder/options.ru +0 -2
- data/test/cgi/assets/folder/test.js +0 -1
- data/test/cgi/assets/fonts/font.eot +0 -1
- data/test/cgi/assets/images/image.png +0 -1
- data/test/cgi/assets/index.html +0 -1
- data/test/cgi/assets/javascripts/app.js +0 -1
- data/test/cgi/assets/stylesheets/app.css +0 -1
- data/test/cgi/lighttpd.conf +0 -26
- data/test/cgi/rackup_stub.rb +0 -6
- data/test/cgi/sample_rackup.ru +0 -5
- data/test/cgi/test +0 -9
- data/test/cgi/test+directory/test+file +0 -1
- data/test/cgi/test.fcgi +0 -9
- data/test/cgi/test.gz +0 -0
- data/test/cgi/test.ru +0 -5
- data/test/gemloader.rb +0 -10
- data/test/helper.rb +0 -34
- data/test/multipart/bad_robots +0 -259
- data/test/multipart/binary +0 -0
- data/test/multipart/content_type_and_no_filename +0 -6
- data/test/multipart/empty +0 -10
- data/test/multipart/fail_16384_nofile +0 -814
- data/test/multipart/file1.txt +0 -1
- data/test/multipart/filename_and_modification_param +0 -7
- data/test/multipart/filename_and_no_name +0 -6
- data/test/multipart/filename_with_encoded_words +0 -7
- data/test/multipart/filename_with_escaped_quotes +0 -6
- data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
- data/test/multipart/filename_with_null_byte +0 -7
- data/test/multipart/filename_with_percent_escaped_quotes +0 -6
- data/test/multipart/filename_with_single_quote +0 -7
- data/test/multipart/filename_with_unescaped_percentages +0 -6
- data/test/multipart/filename_with_unescaped_percentages2 +0 -6
- data/test/multipart/filename_with_unescaped_percentages3 +0 -6
- data/test/multipart/filename_with_unescaped_quotes +0 -6
- data/test/multipart/ie +0 -6
- data/test/multipart/invalid_character +0 -6
- data/test/multipart/mixed_files +0 -21
- data/test/multipart/nested +0 -10
- data/test/multipart/none +0 -9
- data/test/multipart/quoted +0 -15
- data/test/multipart/rack-logo.png +0 -0
- data/test/multipart/semicolon +0 -6
- data/test/multipart/text +0 -15
- data/test/multipart/three_files_three_fields +0 -31
- data/test/multipart/unity3d_wwwform +0 -11
- data/test/multipart/webkit +0 -32
- data/test/rackup/config.ru +0 -31
- data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
- data/test/spec_auth_basic.rb +0 -89
- data/test/spec_auth_digest.rb +0 -260
- data/test/spec_body_proxy.rb +0 -85
- data/test/spec_builder.rb +0 -233
- data/test/spec_cascade.rb +0 -63
- data/test/spec_cgi.rb +0 -84
- data/test/spec_chunked.rb +0 -103
- data/test/spec_common_logger.rb +0 -95
- data/test/spec_conditional_get.rb +0 -103
- data/test/spec_config.rb +0 -23
- data/test/spec_content_length.rb +0 -86
- data/test/spec_content_type.rb +0 -46
- data/test/spec_deflater.rb +0 -375
- data/test/spec_directory.rb +0 -148
- data/test/spec_etag.rb +0 -108
- data/test/spec_events.rb +0 -133
- data/test/spec_fastcgi.rb +0 -85
- data/test/spec_file.rb +0 -264
- data/test/spec_handler.rb +0 -57
- data/test/spec_head.rb +0 -46
- data/test/spec_lint.rb +0 -515
- data/test/spec_lobster.rb +0 -59
- data/test/spec_lock.rb +0 -204
- data/test/spec_logger.rb +0 -24
- data/test/spec_media_type.rb +0 -42
- data/test/spec_method_override.rb +0 -110
- data/test/spec_mime.rb +0 -51
- data/test/spec_mock.rb +0 -359
- data/test/spec_multipart.rb +0 -722
- data/test/spec_null_logger.rb +0 -21
- data/test/spec_recursive.rb +0 -75
- data/test/spec_request.rb +0 -1407
- data/test/spec_response.rb +0 -510
- data/test/spec_rewindable_input.rb +0 -128
- data/test/spec_runtime.rb +0 -50
- data/test/spec_sendfile.rb +0 -125
- data/test/spec_server.rb +0 -193
- data/test/spec_session_abstract_id.rb +0 -31
- data/test/spec_session_abstract_session_hash.rb +0 -45
- data/test/spec_session_cookie.rb +0 -442
- data/test/spec_session_memcache.rb +0 -357
- data/test/spec_session_pool.rb +0 -247
- data/test/spec_show_exceptions.rb +0 -93
- data/test/spec_show_status.rb +0 -104
- data/test/spec_static.rb +0 -184
- data/test/spec_tempfile_reaper.rb +0 -64
- data/test/spec_thin.rb +0 -96
- data/test/spec_urlmap.rb +0 -237
- data/test/spec_utils.rb +0 -742
- data/test/spec_version.rb +0 -11
- data/test/spec_webrick.rb +0 -206
- data/test/static/another/index.html +0 -1
- data/test/static/foo.html +0 -1
- data/test/static/index.html +0 -1
- data/test/testrequest.rb +0 -78
- data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
- data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/lib/rack/handler/lsws.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'lsapi'
|
2
|
-
require 'rack/content_length'
|
3
|
-
require 'rack/rewindable_input'
|
4
4
|
|
5
5
|
module Rack
|
6
6
|
module Handler
|
7
7
|
class LSWS
|
8
|
-
def self.run(app, options
|
8
|
+
def self.run(app, **options)
|
9
9
|
while LSAPI.accept != nil
|
10
10
|
serve app
|
11
11
|
end
|
data/lib/rack/handler/scgi.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'scgi'
|
2
4
|
require 'stringio'
|
3
|
-
require 'rack/content_length'
|
4
|
-
require 'rack/chunked'
|
5
5
|
|
6
6
|
module Rack
|
7
7
|
module Handler
|
8
8
|
class SCGI < ::SCGI::Processor
|
9
9
|
attr_accessor :app
|
10
10
|
|
11
|
-
def self.run(app, options
|
11
|
+
def self.run(app, **options)
|
12
12
|
options[:Socket] = UNIXServer.new(options[:File]) if options[:File]
|
13
|
-
new(options.merge(:app
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
13
|
+
new(options.merge(app: app,
|
14
|
+
host: options[:Host],
|
15
|
+
port: options[:Port],
|
16
|
+
socket: options[:Socket])).listen
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.valid_options
|
@@ -41,7 +41,8 @@ module Rack
|
|
41
41
|
env[QUERY_STRING] ||= ""
|
42
42
|
env[SCRIPT_NAME] = ""
|
43
43
|
|
44
|
-
rack_input = StringIO.new(input_body
|
44
|
+
rack_input = StringIO.new(input_body)
|
45
|
+
rack_input.set_encoding(Encoding::BINARY)
|
45
46
|
|
46
47
|
env.update(
|
47
48
|
RACK_VERSION => Rack::VERSION,
|
data/lib/rack/handler/thin.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "thin"
|
2
4
|
require "thin/server"
|
3
5
|
require "thin/logging"
|
4
6
|
require "thin/backends/tcp_server"
|
5
|
-
require "rack/content_length"
|
6
|
-
require "rack/chunked"
|
7
7
|
|
8
8
|
module Rack
|
9
9
|
module Handler
|
10
10
|
class Thin
|
11
|
-
def self.run(app, options
|
11
|
+
def self.run(app, **options)
|
12
12
|
environment = ENV['RACK_ENV'] || 'development'
|
13
13
|
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
14
14
|
|
data/lib/rack/handler/webrick.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'webrick'
|
2
4
|
require 'stringio'
|
3
|
-
require 'rack/content_length'
|
4
5
|
|
5
6
|
# This monkey patch allows for applications to perform their own chunking
|
6
7
|
# through WEBrick::HTTPResponse if rack is set to true.
|
@@ -22,12 +23,18 @@ end
|
|
22
23
|
module Rack
|
23
24
|
module Handler
|
24
25
|
class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet
|
25
|
-
def self.run(app, options
|
26
|
+
def self.run(app, **options)
|
26
27
|
environment = ENV['RACK_ENV'] || 'development'
|
27
28
|
default_host = environment == 'development' ? 'localhost' : nil
|
28
29
|
|
29
|
-
options[:BindAddress]
|
30
|
+
if !options[:BindAddress] || options[:Host]
|
31
|
+
options[:BindAddress] = options.delete(:Host) || default_host
|
32
|
+
end
|
30
33
|
options[:Port] ||= 8080
|
34
|
+
if options[:SSLEnable]
|
35
|
+
require 'webrick/https'
|
36
|
+
end
|
37
|
+
|
31
38
|
@server = ::WEBrick::HTTPServer.new(options)
|
32
39
|
@server.mount "/", Rack::Handler::WEBrick, app
|
33
40
|
yield @server if block_given?
|
@@ -45,8 +52,10 @@ module Rack
|
|
45
52
|
end
|
46
53
|
|
47
54
|
def self.shutdown
|
48
|
-
@server
|
49
|
-
|
55
|
+
if @server
|
56
|
+
@server.shutdown
|
57
|
+
@server = nil
|
58
|
+
end
|
50
59
|
end
|
51
60
|
|
52
61
|
def initialize(server, app)
|
@@ -79,7 +88,7 @@ module Rack
|
|
79
88
|
env[QUERY_STRING] ||= ""
|
80
89
|
unless env[PATH_INFO] == ""
|
81
90
|
path, n = req.request_uri.path, env[SCRIPT_NAME].length
|
82
|
-
env[PATH_INFO] = path[n, path.length-n]
|
91
|
+
env[PATH_INFO] = path[n, path.length - n]
|
83
92
|
end
|
84
93
|
env[REQUEST_PATH] ||= [env[SCRIPT_NAME], env[PATH_INFO]].join
|
85
94
|
|
data/lib/rack/head.rb
CHANGED
data/lib/rack/lint.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'forwardable'
|
3
4
|
|
4
5
|
module Rack
|
@@ -33,7 +34,7 @@ module Rack
|
|
33
34
|
|
34
35
|
## A Rack application is a Ruby object (not a class) that
|
35
36
|
## responds to +call+.
|
36
|
-
def call(env=nil)
|
37
|
+
def call(env = nil)
|
37
38
|
dup._call(env)
|
38
39
|
end
|
39
40
|
|
@@ -46,13 +47,24 @@ module Rack
|
|
46
47
|
env[RACK_ERRORS] = ErrorWrapper.new(env[RACK_ERRORS])
|
47
48
|
|
48
49
|
## and returns an Array of exactly three values:
|
49
|
-
|
50
|
+
ary = @app.call(env)
|
51
|
+
assert("response #{ary.inspect} is not an Array , but #{ary.class}") {
|
52
|
+
ary.kind_of? Array
|
53
|
+
}
|
54
|
+
assert("response array #{ary.inspect} has #{ary.size} elements instead of 3") {
|
55
|
+
ary.size == 3
|
56
|
+
}
|
57
|
+
|
58
|
+
status, headers, @body = ary
|
50
59
|
## The *status*,
|
51
60
|
check_status status
|
52
61
|
## the *headers*,
|
53
62
|
check_headers headers
|
54
63
|
|
55
|
-
check_hijack_response headers, env
|
64
|
+
hijack_proc = check_hijack_response headers, env
|
65
|
+
if hijack_proc && headers.is_a?(Hash)
|
66
|
+
headers[RACK_HIJACK] = hijack_proc
|
67
|
+
end
|
56
68
|
|
57
69
|
## and the *body*.
|
58
70
|
check_content_type status, headers
|
@@ -63,12 +75,15 @@ module Rack
|
|
63
75
|
|
64
76
|
## == The Environment
|
65
77
|
def check_env(env)
|
66
|
-
## The environment must be an instance of Hash that includes
|
78
|
+
## The environment must be an unfrozen instance of Hash that includes
|
67
79
|
## CGI-like headers. The application is free to modify the
|
68
80
|
## environment.
|
69
81
|
assert("env #{env.inspect} is not a Hash, but #{env.class}") {
|
70
82
|
env.kind_of? Hash
|
71
83
|
}
|
84
|
+
assert("env should not be frozen, but is") {
|
85
|
+
!env.frozen?
|
86
|
+
}
|
72
87
|
|
73
88
|
##
|
74
89
|
## The environment is required to include these variables
|
@@ -102,17 +117,19 @@ module Rack
|
|
102
117
|
## follows the <tt>?</tt>, if any. May be
|
103
118
|
## empty, but is always required!
|
104
119
|
|
105
|
-
## <tt>SERVER_NAME</tt
|
106
|
-
## When combined with <tt>SCRIPT_NAME</tt> and
|
120
|
+
## <tt>SERVER_NAME</tt>:: When combined with <tt>SCRIPT_NAME</tt> and
|
107
121
|
## <tt>PATH_INFO</tt>, these variables can be
|
108
122
|
## used to complete the URL. Note, however,
|
109
123
|
## that <tt>HTTP_HOST</tt>, if present,
|
110
124
|
## should be used in preference to
|
111
125
|
## <tt>SERVER_NAME</tt> for reconstructing
|
112
126
|
## the request URL.
|
113
|
-
## <tt>SERVER_NAME</tt>
|
114
|
-
##
|
115
|
-
|
127
|
+
## <tt>SERVER_NAME</tt> can never be an empty
|
128
|
+
## string, and so is always required.
|
129
|
+
|
130
|
+
## <tt>SERVER_PORT</tt>:: An optional +Integer+ which is the port the
|
131
|
+
## server is running on. Should be specified if
|
132
|
+
## the server is running on a non-standard port.
|
116
133
|
|
117
134
|
## <tt>HTTP_</tt> Variables:: Variables corresponding to the
|
118
135
|
## client-supplied HTTP request
|
@@ -123,9 +140,8 @@ module Rack
|
|
123
140
|
## the presence or absence of the
|
124
141
|
## appropriate HTTP header in the
|
125
142
|
## request. See
|
126
|
-
##
|
127
|
-
##
|
128
|
-
## specific behavior.
|
143
|
+
## {RFC3875 section 4.1.18}[https://tools.ietf.org/html/rfc3875#section-4.1.18]
|
144
|
+
## for specific behavior.
|
129
145
|
|
130
146
|
## In addition to this, the Rack environment must include these
|
131
147
|
## Rack-specific variables:
|
@@ -197,6 +213,11 @@ module Rack
|
|
197
213
|
assert("session #{session.inspect} must respond to clear") {
|
198
214
|
session.respond_to?(:clear)
|
199
215
|
}
|
216
|
+
|
217
|
+
## to_hash (returning unfrozen Hash instance);
|
218
|
+
assert("session #{session.inspect} must respond to to_hash and return unfrozen Hash instance") {
|
219
|
+
session.respond_to?(:to_hash) && session.to_hash.kind_of?(Hash) && !session.to_hash.frozen?
|
220
|
+
}
|
200
221
|
end
|
201
222
|
|
202
223
|
## <tt>rack.logger</tt>:: A common object interface for logging messages.
|
@@ -252,28 +273,49 @@ module Rack
|
|
252
273
|
## accepted specifications and must not be used otherwise.
|
253
274
|
##
|
254
275
|
|
255
|
-
%w[REQUEST_METHOD SERVER_NAME
|
256
|
-
QUERY_STRING
|
276
|
+
%w[REQUEST_METHOD SERVER_NAME QUERY_STRING
|
257
277
|
rack.version rack.input rack.errors
|
258
278
|
rack.multithread rack.multiprocess rack.run_once].each { |header|
|
259
279
|
assert("env missing required key #{header}") { env.include? header }
|
260
280
|
}
|
261
281
|
|
282
|
+
## The <tt>SERVER_PORT</tt> must be an Integer if set.
|
283
|
+
assert("env[SERVER_PORT] is not an Integer") do
|
284
|
+
server_port = env["SERVER_PORT"]
|
285
|
+
server_port.nil? || (Integer(server_port) rescue false)
|
286
|
+
end
|
287
|
+
|
288
|
+
## The <tt>SERVER_NAME</tt> must be a valid authority as defined by RFC7540.
|
289
|
+
assert("#{env[SERVER_NAME]} must be a valid authority") do
|
290
|
+
URI.parse("http://#{env[SERVER_NAME]}/") rescue false
|
291
|
+
end
|
292
|
+
|
293
|
+
## The <tt>HTTP_HOST</tt> must be a valid authority as defined by RFC7540.
|
294
|
+
assert("#{env[HTTP_HOST]} must be a valid authority") do
|
295
|
+
URI.parse("http://#{env[HTTP_HOST]}/") rescue false
|
296
|
+
end
|
297
|
+
|
262
298
|
## The environment must not contain the keys
|
263
299
|
## <tt>HTTP_CONTENT_TYPE</tt> or <tt>HTTP_CONTENT_LENGTH</tt>
|
264
300
|
## (use the versions without <tt>HTTP_</tt>).
|
265
301
|
%w[HTTP_CONTENT_TYPE HTTP_CONTENT_LENGTH].each { |header|
|
266
|
-
assert("env contains #{header}, must use #{header[5
|
302
|
+
assert("env contains #{header}, must use #{header[5, -1]}") {
|
267
303
|
not env.include? header
|
268
304
|
}
|
269
305
|
}
|
270
306
|
|
271
307
|
## The CGI keys (named without a period) must have String values.
|
308
|
+
## If the string values for CGI keys contain non-ASCII characters,
|
309
|
+
## they should use ASCII-8BIT encoding.
|
272
310
|
env.each { |key, value|
|
273
311
|
next if key.include? "." # Skip extensions
|
274
312
|
assert("env variable #{key} has non-string value #{value.inspect}") {
|
275
313
|
value.kind_of? String
|
276
314
|
}
|
315
|
+
next if value.encoding == Encoding::ASCII_8BIT
|
316
|
+
assert("env variable #{key} has value containing non-ASCII characters and has non-ASCII-8BIT encoding #{value.inspect} encoding: #{value.encoding}") {
|
317
|
+
value.b !~ /[\x80-\xff]/n
|
318
|
+
}
|
277
319
|
}
|
278
320
|
|
279
321
|
## There are the following restrictions:
|
@@ -336,7 +378,7 @@ module Rack
|
|
336
378
|
## When applicable, its external encoding must be "ASCII-8BIT" and it
|
337
379
|
## must be opened in binary mode, for Ruby 1.9 compatibility.
|
338
380
|
assert("rack.input #{input} does not have ASCII-8BIT as its external encoding") {
|
339
|
-
input.external_encoding
|
381
|
+
input.external_encoding == Encoding::ASCII_8BIT
|
340
382
|
} if input.respond_to?(:external_encoding)
|
341
383
|
assert("rack.input #{input} is not opened in binary mode") {
|
342
384
|
input.binmode?
|
@@ -568,7 +610,7 @@ module Rack
|
|
568
610
|
|
569
611
|
# this check uses headers like a hash, but the spec only requires
|
570
612
|
# headers respond to #each
|
571
|
-
headers = Rack::Utils::HeaderHash
|
613
|
+
headers = Rack::Utils::HeaderHash[headers]
|
572
614
|
|
573
615
|
## In order to do this, an application may set the special header
|
574
616
|
## <tt>rack.hijack</tt> to an object that responds to <tt>call</tt>
|
@@ -592,7 +634,7 @@ module Rack
|
|
592
634
|
headers[RACK_HIJACK].respond_to? :call
|
593
635
|
}
|
594
636
|
original_hijack = headers[RACK_HIJACK]
|
595
|
-
|
637
|
+
proc do |io|
|
596
638
|
original_hijack.call HijackWrapper.new(io)
|
597
639
|
end
|
598
640
|
else
|
@@ -602,6 +644,8 @@ module Rack
|
|
602
644
|
assert('rack.hijack header must not be present if server does not support hijacking') {
|
603
645
|
headers[RACK_HIJACK].nil?
|
604
646
|
}
|
647
|
+
|
648
|
+
nil
|
605
649
|
end
|
606
650
|
end
|
607
651
|
## ==== Conventions
|
@@ -626,15 +670,17 @@ module Rack
|
|
626
670
|
assert("headers object should respond to #each, but doesn't (got #{header.class} as headers)") {
|
627
671
|
header.respond_to? :each
|
628
672
|
}
|
629
|
-
header.each { |key, value|
|
630
|
-
## Special headers starting "rack." are for communicating with the
|
631
|
-
## server, and must not be sent back to the client.
|
632
|
-
next if key =~ /^rack\..+$/
|
633
673
|
|
674
|
+
header.each { |key, value|
|
634
675
|
## The header keys must be Strings.
|
635
676
|
assert("header key must be a string, was #{key.class}") {
|
636
677
|
key.kind_of? String
|
637
678
|
}
|
679
|
+
|
680
|
+
## Special headers starting "rack." are for communicating with the
|
681
|
+
## server, and must not be sent back to the client.
|
682
|
+
next if key =~ /^rack\..+$/
|
683
|
+
|
638
684
|
## The header must not contain a +Status+ key.
|
639
685
|
assert("header must not contain Status") { key.downcase != "status" }
|
640
686
|
## The header must conform to RFC7230 token specification, i.e. cannot
|
@@ -662,7 +708,7 @@ module Rack
|
|
662
708
|
## 204 or 304.
|
663
709
|
if key.downcase == "content-type"
|
664
710
|
assert("Content-Type header found in #{status} response, not allowed") {
|
665
|
-
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.
|
711
|
+
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.key? status.to_i
|
666
712
|
}
|
667
713
|
return
|
668
714
|
end
|
@@ -676,7 +722,7 @@ module Rack
|
|
676
722
|
## There must not be a <tt>Content-Length</tt> header when the
|
677
723
|
## +Status+ is 1xx, 204 or 304.
|
678
724
|
assert("Content-Length header found in #{status} response, not allowed") {
|
679
|
-
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.
|
725
|
+
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.key? status.to_i
|
680
726
|
}
|
681
727
|
@content_length = value
|
682
728
|
end
|
data/lib/rack/lobster.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'rack/response'
|
3
|
+
require 'zlib'
|
5
4
|
|
6
5
|
module Rack
|
7
6
|
# Paste has a Pony, Rack has a Lobster!
|
@@ -25,8 +24,8 @@ module Rack
|
|
25
24
|
content = ["<title>Lobstericious!</title>",
|
26
25
|
"<pre>", lobster, "</pre>",
|
27
26
|
"<a href='#{href}'>flip!</a>"]
|
28
|
-
length = content.inject(0) { |a,e| a+e.size }.to_s
|
29
|
-
[200, {CONTENT_TYPE => "text/html", CONTENT_LENGTH => length}, content]
|
27
|
+
length = content.inject(0) { |a, e| a + e.size }.to_s
|
28
|
+
[200, { CONTENT_TYPE => "text/html", CONTENT_LENGTH => length }, content]
|
30
29
|
}
|
31
30
|
|
32
31
|
def call(env)
|
@@ -37,8 +36,8 @@ module Rack
|
|
37
36
|
gsub('\\', 'TEMP').
|
38
37
|
gsub('/', '\\').
|
39
38
|
gsub('TEMP', '/').
|
40
|
-
gsub('{','}').
|
41
|
-
gsub('(',')')
|
39
|
+
gsub('{', '}').
|
40
|
+
gsub('(', ')')
|
42
41
|
end.join("\n")
|
43
42
|
href = "?flip=right"
|
44
43
|
elsif req.GET["flip"] == "crash"
|
@@ -62,9 +61,10 @@ module Rack
|
|
62
61
|
end
|
63
62
|
|
64
63
|
if $0 == __FILE__
|
65
|
-
|
66
|
-
|
64
|
+
# :nocov:
|
65
|
+
require_relative '../rack'
|
67
66
|
Rack::Server.start(
|
68
|
-
:
|
67
|
+
app: Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), Port: 9292
|
69
68
|
)
|
69
|
+
# :nocov:
|
70
70
|
end
|
data/lib/rack/lock.rb
CHANGED
data/lib/rack/logger.rb
CHANGED
data/lib/rack/media_type.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rack
|
2
4
|
# Rack::MediaType parse media type and parameters out of content_type string
|
3
5
|
|
@@ -13,7 +15,7 @@ module Rack
|
|
13
15
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
|
14
16
|
def type(content_type)
|
15
17
|
return nil unless content_type
|
16
|
-
content_type.split(SPLIT_PATTERN, 2).first.downcase
|
18
|
+
content_type.split(SPLIT_PATTERN, 2).first.tap &:downcase!
|
17
19
|
end
|
18
20
|
|
19
21
|
# The media type parameters provided in CONTENT_TYPE as a Hash, or
|
@@ -23,15 +25,18 @@ module Rack
|
|
23
25
|
# { 'charset' => 'utf-8' }
|
24
26
|
def params(content_type)
|
25
27
|
return {} if content_type.nil?
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
|
29
|
+
content_type.split(SPLIT_PATTERN)[1..-1].each_with_object({}) do |s, hsh|
|
30
|
+
k, v = s.split('=', 2)
|
31
|
+
|
32
|
+
hsh[k.tap(&:downcase!)] = strip_doublequotes(v)
|
33
|
+
end
|
29
34
|
end
|
30
35
|
|
31
36
|
private
|
32
37
|
|
33
38
|
def strip_doublequotes(str)
|
34
|
-
(str
|
39
|
+
(str.start_with?('"') && str.end_with?('"')) ? str[1..-2] : str
|
35
40
|
end
|
36
41
|
end
|
37
42
|
end
|