rack 2.2.10 → 3.0.0
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 +152 -100
- data/CONTRIBUTING.md +53 -47
- data/MIT-LICENSE +1 -1
- data/README.md +293 -0
- data/SPEC.rdoc +174 -126
- data/lib/rack/auth/abstract/handler.rb +3 -1
- data/lib/rack/auth/abstract/request.rb +3 -1
- data/lib/rack/auth/basic.rb +2 -1
- data/lib/rack/auth/digest/md5.rb +1 -131
- data/lib/rack/auth/digest/nonce.rb +1 -53
- data/lib/rack/auth/digest/params.rb +1 -54
- data/lib/rack/auth/digest/request.rb +1 -43
- data/lib/rack/auth/digest.rb +256 -0
- data/lib/rack/body_proxy.rb +3 -1
- data/lib/rack/builder.rb +60 -42
- data/lib/rack/cascade.rb +2 -0
- data/lib/rack/chunked.rb +16 -13
- data/lib/rack/common_logger.rb +23 -18
- data/lib/rack/conditional_get.rb +18 -15
- data/lib/rack/constants.rb +63 -0
- data/lib/rack/content_length.rb +12 -16
- data/lib/rack/content_type.rb +8 -5
- data/lib/rack/deflater.rb +40 -26
- data/lib/rack/directory.rb +9 -3
- data/lib/rack/etag.rb +14 -23
- data/lib/rack/events.rb +4 -0
- data/lib/rack/file.rb +2 -0
- data/lib/rack/files.rb +15 -17
- data/lib/rack/head.rb +9 -8
- data/lib/rack/headers.rb +154 -0
- data/lib/rack/lint.rb +754 -648
- data/lib/rack/lock.rb +2 -5
- data/lib/rack/logger.rb +2 -0
- data/lib/rack/media_type.rb +4 -9
- data/lib/rack/method_override.rb +5 -1
- data/lib/rack/mime.rb +8 -0
- data/lib/rack/mock.rb +1 -271
- data/lib/rack/mock_request.rb +166 -0
- data/lib/rack/mock_response.rb +126 -0
- data/lib/rack/multipart/generator.rb +7 -5
- data/lib/rack/multipart/parser.rb +123 -85
- data/lib/rack/multipart/uploaded_file.rb +4 -0
- data/lib/rack/multipart.rb +20 -40
- data/lib/rack/null_logger.rb +9 -0
- data/lib/rack/query_parser.rb +76 -44
- data/lib/rack/recursive.rb +2 -0
- data/lib/rack/reloader.rb +0 -2
- data/lib/rack/request.rb +189 -91
- data/lib/rack/response.rb +131 -61
- data/lib/rack/rewindable_input.rb +24 -5
- data/lib/rack/runtime.rb +7 -6
- data/lib/rack/sendfile.rb +30 -25
- data/lib/rack/show_exceptions.rb +15 -2
- data/lib/rack/show_status.rb +17 -7
- data/lib/rack/static.rb +8 -8
- data/lib/rack/tempfile_reaper.rb +15 -4
- data/lib/rack/urlmap.rb +4 -2
- data/lib/rack/utils.rb +212 -202
- data/lib/rack/version.rb +9 -4
- data/lib/rack.rb +5 -76
- metadata +15 -35
- data/README.rdoc +0 -320
- data/Rakefile +0 -130
- data/bin/rackup +0 -5
- data/contrib/rack.png +0 -0
- data/contrib/rack.svg +0 -150
- data/contrib/rack_logo.svg +0 -164
- data/contrib/rdoc.css +0 -412
- data/example/lobster.ru +0 -6
- data/example/protectedlobster.rb +0 -16
- data/example/protectedlobster.ru +0 -10
- data/lib/rack/core_ext/regexp.rb +0 -14
- data/lib/rack/handler/cgi.rb +0 -59
- data/lib/rack/handler/fastcgi.rb +0 -100
- data/lib/rack/handler/lsws.rb +0 -61
- data/lib/rack/handler/scgi.rb +0 -71
- data/lib/rack/handler/thin.rb +0 -36
- data/lib/rack/handler/webrick.rb +0 -129
- data/lib/rack/handler.rb +0 -104
- data/lib/rack/lobster.rb +0 -70
- data/lib/rack/server.rb +0 -466
- data/lib/rack/session/abstract/id.rb +0 -523
- data/lib/rack/session/cookie.rb +0 -203
- data/lib/rack/session/memcache.rb +0 -10
- data/lib/rack/session/pool.rb +0 -85
- data/rack.gemspec +0 -46
data/lib/rack/handler/scgi.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'scgi'
|
4
|
-
require 'stringio'
|
5
|
-
|
6
|
-
module Rack
|
7
|
-
module Handler
|
8
|
-
class SCGI < ::SCGI::Processor
|
9
|
-
attr_accessor :app
|
10
|
-
|
11
|
-
def self.run(app, **options)
|
12
|
-
options[:Socket] = UNIXServer.new(options[:File]) if options[:File]
|
13
|
-
new(options.merge(app: app,
|
14
|
-
host: options[:Host],
|
15
|
-
port: options[:Port],
|
16
|
-
socket: options[:Socket])).listen
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.valid_options
|
20
|
-
environment = ENV['RACK_ENV'] || 'development'
|
21
|
-
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
22
|
-
|
23
|
-
{
|
24
|
-
"Host=HOST" => "Hostname to listen on (default: #{default_host})",
|
25
|
-
"Port=PORT" => "Port to listen on (default: 8080)",
|
26
|
-
}
|
27
|
-
end
|
28
|
-
|
29
|
-
def initialize(settings = {})
|
30
|
-
@app = settings[:app]
|
31
|
-
super(settings)
|
32
|
-
end
|
33
|
-
|
34
|
-
def process_request(request, input_body, socket)
|
35
|
-
env = Hash[request]
|
36
|
-
env.delete "HTTP_CONTENT_TYPE"
|
37
|
-
env.delete "HTTP_CONTENT_LENGTH"
|
38
|
-
env[REQUEST_PATH], env[QUERY_STRING] = env["REQUEST_URI"].split('?', 2)
|
39
|
-
env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
|
40
|
-
env[PATH_INFO] = env[REQUEST_PATH]
|
41
|
-
env[QUERY_STRING] ||= ""
|
42
|
-
env[SCRIPT_NAME] = ""
|
43
|
-
|
44
|
-
rack_input = StringIO.new(input_body)
|
45
|
-
rack_input.set_encoding(Encoding::BINARY)
|
46
|
-
|
47
|
-
env.update(
|
48
|
-
RACK_VERSION => Rack::VERSION,
|
49
|
-
RACK_INPUT => rack_input,
|
50
|
-
RACK_ERRORS => $stderr,
|
51
|
-
RACK_MULTITHREAD => true,
|
52
|
-
RACK_MULTIPROCESS => true,
|
53
|
-
RACK_RUNONCE => false,
|
54
|
-
RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[HTTPS]) ? "https" : "http"
|
55
|
-
)
|
56
|
-
|
57
|
-
status, headers, body = app.call(env)
|
58
|
-
begin
|
59
|
-
socket.write("Status: #{status}\r\n")
|
60
|
-
headers.each do |k, vs|
|
61
|
-
vs.split("\n").each { |v| socket.write("#{k}: #{v}\r\n")}
|
62
|
-
end
|
63
|
-
socket.write("\r\n")
|
64
|
-
body.each {|s| socket.write(s)}
|
65
|
-
ensure
|
66
|
-
body.close if body.respond_to? :close
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
data/lib/rack/handler/thin.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "thin"
|
4
|
-
require "thin/server"
|
5
|
-
require "thin/logging"
|
6
|
-
require "thin/backends/tcp_server"
|
7
|
-
|
8
|
-
module Rack
|
9
|
-
module Handler
|
10
|
-
class Thin
|
11
|
-
def self.run(app, **options)
|
12
|
-
environment = ENV['RACK_ENV'] || 'development'
|
13
|
-
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
14
|
-
|
15
|
-
host = options.delete(:Host) || default_host
|
16
|
-
port = options.delete(:Port) || 8080
|
17
|
-
args = [host, port, app, options]
|
18
|
-
# Thin versions below 0.8.0 do not support additional options
|
19
|
-
args.pop if ::Thin::VERSION::MAJOR < 1 && ::Thin::VERSION::MINOR < 8
|
20
|
-
server = ::Thin::Server.new(*args)
|
21
|
-
yield server if block_given?
|
22
|
-
server.start
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.valid_options
|
26
|
-
environment = ENV['RACK_ENV'] || 'development'
|
27
|
-
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
28
|
-
|
29
|
-
{
|
30
|
-
"Host=HOST" => "Hostname to listen on (default: #{default_host})",
|
31
|
-
"Port=PORT" => "Port to listen on (default: 8080)",
|
32
|
-
}
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/lib/rack/handler/webrick.rb
DELETED
@@ -1,129 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'webrick'
|
4
|
-
require 'stringio'
|
5
|
-
|
6
|
-
# This monkey patch allows for applications to perform their own chunking
|
7
|
-
# through WEBrick::HTTPResponse if rack is set to true.
|
8
|
-
class WEBrick::HTTPResponse
|
9
|
-
attr_accessor :rack
|
10
|
-
|
11
|
-
alias _rack_setup_header setup_header
|
12
|
-
def setup_header
|
13
|
-
app_chunking = rack && @header['transfer-encoding'] == 'chunked'
|
14
|
-
|
15
|
-
@chunked = app_chunking if app_chunking
|
16
|
-
|
17
|
-
_rack_setup_header
|
18
|
-
|
19
|
-
@chunked = false if app_chunking
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
module Rack
|
24
|
-
module Handler
|
25
|
-
class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet
|
26
|
-
def self.run(app, **options)
|
27
|
-
environment = ENV['RACK_ENV'] || 'development'
|
28
|
-
default_host = environment == 'development' ? 'localhost' : nil
|
29
|
-
|
30
|
-
if !options[:BindAddress] || options[:Host]
|
31
|
-
options[:BindAddress] = options.delete(:Host) || default_host
|
32
|
-
end
|
33
|
-
options[:Port] ||= 8080
|
34
|
-
if options[:SSLEnable]
|
35
|
-
require 'webrick/https'
|
36
|
-
end
|
37
|
-
|
38
|
-
@server = ::WEBrick::HTTPServer.new(options)
|
39
|
-
@server.mount "/", Rack::Handler::WEBrick, app
|
40
|
-
yield @server if block_given?
|
41
|
-
@server.start
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.valid_options
|
45
|
-
environment = ENV['RACK_ENV'] || 'development'
|
46
|
-
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
47
|
-
|
48
|
-
{
|
49
|
-
"Host=HOST" => "Hostname to listen on (default: #{default_host})",
|
50
|
-
"Port=PORT" => "Port to listen on (default: 8080)",
|
51
|
-
}
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.shutdown
|
55
|
-
if @server
|
56
|
-
@server.shutdown
|
57
|
-
@server = nil
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def initialize(server, app)
|
62
|
-
super server
|
63
|
-
@app = app
|
64
|
-
end
|
65
|
-
|
66
|
-
def service(req, res)
|
67
|
-
res.rack = true
|
68
|
-
env = req.meta_vars
|
69
|
-
env.delete_if { |k, v| v.nil? }
|
70
|
-
|
71
|
-
rack_input = StringIO.new(req.body.to_s)
|
72
|
-
rack_input.set_encoding(Encoding::BINARY)
|
73
|
-
|
74
|
-
env.update(
|
75
|
-
RACK_VERSION => Rack::VERSION,
|
76
|
-
RACK_INPUT => rack_input,
|
77
|
-
RACK_ERRORS => $stderr,
|
78
|
-
RACK_MULTITHREAD => true,
|
79
|
-
RACK_MULTIPROCESS => false,
|
80
|
-
RACK_RUNONCE => false,
|
81
|
-
RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[HTTPS]) ? "https" : "http",
|
82
|
-
RACK_IS_HIJACK => true,
|
83
|
-
RACK_HIJACK => lambda { raise NotImplementedError, "only partial hijack is supported."},
|
84
|
-
RACK_HIJACK_IO => nil
|
85
|
-
)
|
86
|
-
|
87
|
-
env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
|
88
|
-
env[QUERY_STRING] ||= ""
|
89
|
-
unless env[PATH_INFO] == ""
|
90
|
-
path, n = req.request_uri.path, env[SCRIPT_NAME].length
|
91
|
-
env[PATH_INFO] = path[n, path.length - n]
|
92
|
-
end
|
93
|
-
env[REQUEST_PATH] ||= [env[SCRIPT_NAME], env[PATH_INFO]].join
|
94
|
-
|
95
|
-
status, headers, body = @app.call(env)
|
96
|
-
begin
|
97
|
-
res.status = status.to_i
|
98
|
-
io_lambda = nil
|
99
|
-
headers.each { |k, vs|
|
100
|
-
if k == RACK_HIJACK
|
101
|
-
io_lambda = vs
|
102
|
-
elsif k.downcase == "set-cookie"
|
103
|
-
res.cookies.concat vs.split("\n")
|
104
|
-
else
|
105
|
-
# Since WEBrick won't accept repeated headers,
|
106
|
-
# merge the values per RFC 1945 section 4.2.
|
107
|
-
res[k] = vs.split("\n").join(", ")
|
108
|
-
end
|
109
|
-
}
|
110
|
-
|
111
|
-
if io_lambda
|
112
|
-
rd, wr = IO.pipe
|
113
|
-
res.body = rd
|
114
|
-
res.chunked = true
|
115
|
-
io_lambda.call wr
|
116
|
-
elsif body.respond_to?(:to_path)
|
117
|
-
res.body = ::File.open(body.to_path, 'rb')
|
118
|
-
else
|
119
|
-
body.each { |part|
|
120
|
-
res.body << part
|
121
|
-
}
|
122
|
-
end
|
123
|
-
ensure
|
124
|
-
body.close if body.respond_to? :close
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
data/lib/rack/handler.rb
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Rack
|
4
|
-
# *Handlers* connect web servers with Rack.
|
5
|
-
#
|
6
|
-
# Rack includes Handlers for Thin, WEBrick, FastCGI, CGI, SCGI
|
7
|
-
# and LiteSpeed.
|
8
|
-
#
|
9
|
-
# Handlers usually are activated by calling <tt>MyHandler.run(myapp)</tt>.
|
10
|
-
# A second optional hash can be passed to include server-specific
|
11
|
-
# configuration.
|
12
|
-
module Handler
|
13
|
-
def self.get(server)
|
14
|
-
return unless server
|
15
|
-
server = server.to_s
|
16
|
-
|
17
|
-
unless @handlers.include? server
|
18
|
-
load_error = try_require('rack/handler', server)
|
19
|
-
end
|
20
|
-
|
21
|
-
if klass = @handlers[server]
|
22
|
-
const_get(klass)
|
23
|
-
else
|
24
|
-
const_get(server, false)
|
25
|
-
end
|
26
|
-
|
27
|
-
rescue NameError => name_error
|
28
|
-
raise load_error || name_error
|
29
|
-
end
|
30
|
-
|
31
|
-
# Select first available Rack handler given an `Array` of server names.
|
32
|
-
# Raises `LoadError` if no handler was found.
|
33
|
-
#
|
34
|
-
# > pick ['thin', 'webrick']
|
35
|
-
# => Rack::Handler::WEBrick
|
36
|
-
def self.pick(server_names)
|
37
|
-
server_names = Array(server_names)
|
38
|
-
server_names.each do |server_name|
|
39
|
-
begin
|
40
|
-
return get(server_name.to_s)
|
41
|
-
rescue LoadError, NameError
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
raise LoadError, "Couldn't find handler for: #{server_names.join(', ')}."
|
46
|
-
end
|
47
|
-
|
48
|
-
SERVER_NAMES = %w(puma thin falcon webrick).freeze
|
49
|
-
private_constant :SERVER_NAMES
|
50
|
-
|
51
|
-
def self.default
|
52
|
-
# Guess.
|
53
|
-
if ENV.include?("PHP_FCGI_CHILDREN")
|
54
|
-
Rack::Handler::FastCGI
|
55
|
-
elsif ENV.include?(REQUEST_METHOD)
|
56
|
-
Rack::Handler::CGI
|
57
|
-
elsif ENV.include?("RACK_HANDLER")
|
58
|
-
self.get(ENV["RACK_HANDLER"])
|
59
|
-
else
|
60
|
-
pick SERVER_NAMES
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# Transforms server-name constants to their canonical form as filenames,
|
65
|
-
# then tries to require them but silences the LoadError if not found
|
66
|
-
#
|
67
|
-
# Naming convention:
|
68
|
-
#
|
69
|
-
# Foo # => 'foo'
|
70
|
-
# FooBar # => 'foo_bar.rb'
|
71
|
-
# FooBAR # => 'foobar.rb'
|
72
|
-
# FOObar # => 'foobar.rb'
|
73
|
-
# FOOBAR # => 'foobar.rb'
|
74
|
-
# FooBarBaz # => 'foo_bar_baz.rb'
|
75
|
-
def self.try_require(prefix, const_name)
|
76
|
-
file = const_name.gsub(/^[A-Z]+/) { |pre| pre.downcase }.
|
77
|
-
gsub(/[A-Z]+[^A-Z]/, '_\&').downcase
|
78
|
-
|
79
|
-
require(::File.join(prefix, file))
|
80
|
-
nil
|
81
|
-
rescue LoadError => error
|
82
|
-
error
|
83
|
-
end
|
84
|
-
|
85
|
-
def self.register(server, klass)
|
86
|
-
@handlers ||= {}
|
87
|
-
@handlers[server.to_s] = klass.to_s
|
88
|
-
end
|
89
|
-
|
90
|
-
autoload :CGI, "rack/handler/cgi"
|
91
|
-
autoload :FastCGI, "rack/handler/fastcgi"
|
92
|
-
autoload :WEBrick, "rack/handler/webrick"
|
93
|
-
autoload :LSWS, "rack/handler/lsws"
|
94
|
-
autoload :SCGI, "rack/handler/scgi"
|
95
|
-
autoload :Thin, "rack/handler/thin"
|
96
|
-
|
97
|
-
register 'cgi', 'Rack::Handler::CGI'
|
98
|
-
register 'fastcgi', 'Rack::Handler::FastCGI'
|
99
|
-
register 'webrick', 'Rack::Handler::WEBrick'
|
100
|
-
register 'lsws', 'Rack::Handler::LSWS'
|
101
|
-
register 'scgi', 'Rack::Handler::SCGI'
|
102
|
-
register 'thin', 'Rack::Handler::Thin'
|
103
|
-
end
|
104
|
-
end
|
data/lib/rack/lobster.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'zlib'
|
4
|
-
|
5
|
-
module Rack
|
6
|
-
# Paste has a Pony, Rack has a Lobster!
|
7
|
-
class Lobster
|
8
|
-
LobsterString = Zlib::Inflate.inflate("eJx9kEEOwyAMBO99xd7MAcytUhPlJyj2
|
9
|
-
P6jy9i4k9EQyGAnBarEXeCBqSkntNXsi/ZCvC48zGQoZKikGrFMZvgS5ZHd+aGWVuWwhVF0
|
10
|
-
t1drVmiR42HcWNz5w3QanT+2gIvTVCiE1lm1Y0eU4JGmIIbaKwextKn8rvW+p5PIwFl8ZWJ
|
11
|
-
I8jyiTlhTcYXkekJAzTyYN6E08A+dk8voBkAVTJQ==".delete("\n ").unpack("m*")[0])
|
12
|
-
|
13
|
-
LambdaLobster = lambda { |env|
|
14
|
-
if env[QUERY_STRING].include?("flip")
|
15
|
-
lobster = LobsterString.split("\n").
|
16
|
-
map { |line| line.ljust(42).reverse }.
|
17
|
-
join("\n")
|
18
|
-
href = "?"
|
19
|
-
else
|
20
|
-
lobster = LobsterString
|
21
|
-
href = "?flip"
|
22
|
-
end
|
23
|
-
|
24
|
-
content = ["<title>Lobstericious!</title>",
|
25
|
-
"<pre>", lobster, "</pre>",
|
26
|
-
"<a href='#{href}'>flip!</a>"]
|
27
|
-
length = content.inject(0) { |a, e| a + e.size }.to_s
|
28
|
-
[200, { CONTENT_TYPE => "text/html", CONTENT_LENGTH => length }, content]
|
29
|
-
}
|
30
|
-
|
31
|
-
def call(env)
|
32
|
-
req = Request.new(env)
|
33
|
-
if req.GET["flip"] == "left"
|
34
|
-
lobster = LobsterString.split("\n").map do |line|
|
35
|
-
line.ljust(42).reverse.
|
36
|
-
gsub('\\', 'TEMP').
|
37
|
-
gsub('/', '\\').
|
38
|
-
gsub('TEMP', '/').
|
39
|
-
gsub('{', '}').
|
40
|
-
gsub('(', ')')
|
41
|
-
end.join("\n")
|
42
|
-
href = "?flip=right"
|
43
|
-
elsif req.GET["flip"] == "crash"
|
44
|
-
raise "Lobster crashed"
|
45
|
-
else
|
46
|
-
lobster = LobsterString
|
47
|
-
href = "?flip=left"
|
48
|
-
end
|
49
|
-
|
50
|
-
res = Response.new
|
51
|
-
res.write "<title>Lobstericious!</title>"
|
52
|
-
res.write "<pre>"
|
53
|
-
res.write lobster
|
54
|
-
res.write "</pre>"
|
55
|
-
res.write "<p><a href='#{href}'>flip!</a></p>"
|
56
|
-
res.write "<p><a href='?flip=crash'>crash!</a></p>"
|
57
|
-
res.finish
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
if $0 == __FILE__
|
64
|
-
# :nocov:
|
65
|
-
require_relative '../rack'
|
66
|
-
Rack::Server.start(
|
67
|
-
app: Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), Port: 9292
|
68
|
-
)
|
69
|
-
# :nocov:
|
70
|
-
end
|