rack 1.1.6 → 1.6.9
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 +7 -0
- data/COPYING +1 -1
- data/HISTORY.md +375 -0
- data/KNOWN-ISSUES +23 -0
- data/README.rdoc +312 -0
- data/Rakefile +124 -0
- data/SPEC +125 -32
- data/contrib/rack.png +0 -0
- data/contrib/rack.svg +150 -0
- data/contrib/rack_logo.svg +1 -1
- data/contrib/rdoc.css +412 -0
- data/example/protectedlobster.rb +1 -1
- data/lib/rack/auth/abstract/handler.rb +4 -4
- data/lib/rack/auth/abstract/request.rb +7 -5
- data/lib/rack/auth/basic.rb +1 -1
- data/lib/rack/auth/digest/md5.rb +7 -3
- data/lib/rack/auth/digest/nonce.rb +1 -1
- data/lib/rack/auth/digest/params.rb +7 -9
- data/lib/rack/auth/digest/request.rb +10 -9
- data/lib/rack/backports/uri/common_18.rb +56 -0
- data/lib/rack/backports/uri/common_192.rb +52 -0
- data/lib/rack/backports/uri/common_193.rb +29 -0
- data/lib/rack/body_proxy.rb +39 -0
- data/lib/rack/builder.rb +106 -22
- data/lib/rack/cascade.rb +17 -6
- data/lib/rack/chunked.rb +44 -24
- data/lib/rack/commonlogger.rb +36 -13
- data/lib/rack/conditionalget.rb +49 -17
- data/lib/rack/config.rb +5 -0
- data/lib/rack/content_length.rb +14 -6
- data/lib/rack/content_type.rb +7 -1
- data/lib/rack/deflater.rb +73 -15
- data/lib/rack/directory.rb +18 -8
- data/lib/rack/etag.rb +59 -9
- data/lib/rack/file.rb +106 -44
- data/lib/rack/handler/cgi.rb +11 -11
- data/lib/rack/handler/fastcgi.rb +18 -6
- data/lib/rack/handler/lsws.rb +2 -4
- data/lib/rack/handler/mongrel.rb +22 -6
- data/lib/rack/handler/scgi.rb +16 -8
- data/lib/rack/handler/thin.rb +19 -4
- data/lib/rack/handler/webrick.rb +72 -19
- data/lib/rack/handler.rb +47 -14
- data/lib/rack/head.rb +10 -2
- data/lib/rack/lint.rb +260 -75
- data/lib/rack/lobster.rb +13 -8
- data/lib/rack/lock.rb +13 -3
- data/lib/rack/logger.rb +0 -2
- data/lib/rack/methodoverride.rb +27 -8
- data/lib/rack/mime.rb +625 -167
- data/lib/rack/mock.rb +78 -53
- data/lib/rack/multipart/generator.rb +93 -0
- data/lib/rack/multipart/parser.rb +253 -0
- data/lib/rack/multipart/uploaded_file.rb +34 -0
- data/lib/rack/multipart.rb +34 -0
- data/lib/rack/nulllogger.rb +21 -2
- data/lib/rack/recursive.rb +10 -5
- data/lib/rack/reloader.rb +3 -2
- data/lib/rack/request.rb +201 -74
- data/lib/rack/response.rb +41 -28
- data/lib/rack/rewindable_input.rb +15 -11
- data/lib/rack/runtime.rb +16 -3
- data/lib/rack/sendfile.rb +47 -29
- data/lib/rack/server.rb +223 -47
- data/lib/rack/session/abstract/id.rb +289 -30
- data/lib/rack/session/cookie.rb +133 -44
- data/lib/rack/session/memcache.rb +30 -56
- data/lib/rack/session/pool.rb +19 -43
- data/lib/rack/showexceptions.rb +53 -15
- data/lib/rack/showstatus.rb +14 -7
- data/lib/rack/static.rb +124 -12
- data/lib/rack/tempfile_reaper.rb +22 -0
- data/lib/rack/urlmap.rb +49 -15
- data/lib/rack/utils/okjson.rb +600 -0
- data/lib/rack/utils.rb +363 -361
- data/lib/rack.rb +17 -23
- data/rack.gemspec +11 -20
- data/test/builder/anything.rb +5 -0
- data/test/builder/comment.ru +4 -0
- data/test/builder/end.ru +5 -0
- data/test/builder/line.ru +1 -0
- data/test/builder/options.ru +2 -0
- data/test/cgi/assets/folder/test.js +1 -0
- data/test/cgi/assets/fonts/font.eot +1 -0
- data/test/cgi/assets/images/image.png +1 -0
- data/test/cgi/assets/index.html +1 -0
- data/test/cgi/assets/javascripts/app.js +1 -0
- data/test/cgi/assets/stylesheets/app.css +1 -0
- data/test/cgi/lighttpd.conf +26 -0
- data/test/cgi/rackup_stub.rb +6 -0
- data/test/cgi/sample_rackup.ru +5 -0
- data/test/cgi/test +9 -0
- data/test/cgi/test+directory/test+file +1 -0
- data/test/cgi/test.fcgi +8 -0
- data/test/cgi/test.ru +5 -0
- data/test/gemloader.rb +10 -0
- data/test/multipart/bad_robots +259 -0
- data/test/multipart/binary +0 -0
- data/test/multipart/content_type_and_no_filename +6 -0
- data/test/multipart/empty +10 -0
- data/test/multipart/fail_16384_nofile +814 -0
- data/test/multipart/file1.txt +1 -0
- data/test/multipart/filename_and_modification_param +7 -0
- data/test/multipart/filename_and_no_name +6 -0
- data/test/multipart/filename_with_escaped_quotes +6 -0
- data/test/multipart/filename_with_escaped_quotes_and_modification_param +7 -0
- data/test/multipart/filename_with_null_byte +7 -0
- data/test/multipart/filename_with_percent_escaped_quotes +6 -0
- data/test/multipart/filename_with_unescaped_percentages +6 -0
- data/test/multipart/filename_with_unescaped_percentages2 +6 -0
- data/test/multipart/filename_with_unescaped_percentages3 +6 -0
- data/test/multipart/filename_with_unescaped_quotes +6 -0
- data/test/multipart/ie +6 -0
- data/test/multipart/invalid_character +6 -0
- data/test/multipart/mixed_files +21 -0
- data/test/multipart/nested +10 -0
- data/test/multipart/none +9 -0
- data/test/multipart/semicolon +6 -0
- data/test/multipart/text +15 -0
- data/test/multipart/three_files_three_fields +31 -0
- data/test/multipart/webkit +32 -0
- data/test/rackup/config.ru +31 -0
- data/test/registering_handler/rack/handler/registering_myself.rb +8 -0
- data/test/{spec_rack_auth_basic.rb → spec_auth_basic.rb} +23 -15
- data/test/{spec_rack_auth_digest.rb → spec_auth_digest.rb} +56 -29
- data/test/spec_body_proxy.rb +85 -0
- data/test/spec_builder.rb +223 -0
- data/test/{spec_rack_cascade.rb → spec_cascade.rb} +28 -15
- data/test/{spec_rack_cgi.rb → spec_cgi.rb} +44 -31
- data/test/spec_chunked.rb +101 -0
- data/test/spec_commonlogger.rb +93 -0
- data/test/spec_conditionalget.rb +102 -0
- data/test/{spec_rack_config.rb → spec_config.rb} +6 -8
- data/test/spec_content_length.rb +85 -0
- data/test/spec_content_type.rb +45 -0
- data/test/spec_deflater.rb +339 -0
- data/test/{spec_rack_directory.rb → spec_directory.rb} +37 -10
- data/test/spec_etag.rb +107 -0
- data/test/{spec_rack_fastcgi.rb → spec_fastcgi.rb} +47 -29
- data/test/spec_file.rb +221 -0
- data/test/spec_handler.rb +72 -0
- data/test/spec_head.rb +45 -0
- data/test/{spec_rack_lint.rb → spec_lint.rb} +82 -60
- data/test/spec_lobster.rb +58 -0
- data/test/spec_lock.rb +164 -0
- data/test/spec_logger.rb +23 -0
- data/test/spec_methodoverride.rb +95 -0
- data/test/spec_mime.rb +51 -0
- data/test/{spec_rack_mock.rb → spec_mock.rb} +92 -38
- data/test/{spec_rack_mongrel.rb → spec_mongrel.rb} +46 -53
- data/test/spec_multipart.rb +600 -0
- data/test/spec_nulllogger.rb +20 -0
- data/test/spec_recursive.rb +72 -0
- data/test/spec_request.rb +1227 -0
- data/test/spec_response.rb +407 -0
- data/test/spec_rewindable_input.rb +118 -0
- data/test/spec_runtime.rb +49 -0
- data/test/spec_sendfile.rb +130 -0
- data/test/spec_server.rb +167 -0
- data/test/spec_session_abstract_id.rb +53 -0
- data/test/spec_session_cookie.rb +410 -0
- data/test/{spec_rack_session_memcache.rb → spec_session_memcache.rb} +119 -71
- data/test/{spec_rack_session_pool.rb → spec_session_pool.rb} +106 -69
- data/test/spec_showexceptions.rb +85 -0
- data/test/spec_showstatus.rb +103 -0
- data/test/spec_static.rb +145 -0
- data/test/spec_tempfile_reaper.rb +63 -0
- data/test/{spec_rack_thin.rb → spec_thin.rb} +35 -35
- data/test/{spec_rack_urlmap.rb → spec_urlmap.rb} +40 -19
- data/test/spec_utils.rb +647 -0
- data/test/spec_version.rb +17 -0
- data/test/spec_webrick.rb +184 -0
- data/test/static/another/index.html +1 -0
- data/test/static/index.html +1 -0
- data/test/testrequest.rb +78 -0
- data/test/unregistered_handler/rack/handler/unregistered.rb +7 -0
- data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
- metadata +220 -239
- data/RDOX +0 -0
- data/README +0 -592
- data/lib/rack/adapter/camping.rb +0 -22
- data/test/spec_auth.rb +0 -57
- data/test/spec_rack_builder.rb +0 -84
- data/test/spec_rack_camping.rb +0 -55
- data/test/spec_rack_chunked.rb +0 -62
- data/test/spec_rack_commonlogger.rb +0 -61
- data/test/spec_rack_conditionalget.rb +0 -41
- data/test/spec_rack_content_length.rb +0 -43
- data/test/spec_rack_content_type.rb +0 -30
- data/test/spec_rack_deflater.rb +0 -127
- data/test/spec_rack_etag.rb +0 -17
- data/test/spec_rack_file.rb +0 -75
- data/test/spec_rack_handler.rb +0 -43
- data/test/spec_rack_head.rb +0 -30
- data/test/spec_rack_lobster.rb +0 -45
- data/test/spec_rack_lock.rb +0 -38
- data/test/spec_rack_logger.rb +0 -21
- data/test/spec_rack_methodoverride.rb +0 -60
- data/test/spec_rack_nulllogger.rb +0 -13
- data/test/spec_rack_recursive.rb +0 -77
- data/test/spec_rack_request.rb +0 -594
- data/test/spec_rack_response.rb +0 -221
- data/test/spec_rack_rewindable_input.rb +0 -118
- data/test/spec_rack_runtime.rb +0 -35
- data/test/spec_rack_sendfile.rb +0 -86
- data/test/spec_rack_session_cookie.rb +0 -92
- data/test/spec_rack_showexceptions.rb +0 -21
- data/test/spec_rack_showstatus.rb +0 -72
- data/test/spec_rack_static.rb +0 -37
- data/test/spec_rack_utils.rb +0 -557
- data/test/spec_rack_webrick.rb +0 -130
- data/test/spec_rackup.rb +0 -164
data/lib/rack/handler/cgi.rb
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
require 'rack/content_length'
|
|
2
|
+
require 'rack/rewindable_input'
|
|
2
3
|
|
|
3
4
|
module Rack
|
|
4
5
|
module Handler
|
|
5
6
|
class CGI
|
|
6
7
|
def self.run(app, options=nil)
|
|
8
|
+
$stdin.binmode
|
|
7
9
|
serve app
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
def self.serve(app)
|
|
11
|
-
app = ContentLength.new(app)
|
|
12
|
-
|
|
13
13
|
env = ENV.to_hash
|
|
14
14
|
env.delete "HTTP_CONTENT_LENGTH"
|
|
15
15
|
|
|
16
16
|
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
|
|
17
17
|
|
|
18
|
-
env.update({"rack.version" =>
|
|
19
|
-
"rack.input" => $stdin,
|
|
18
|
+
env.update({"rack.version" => Rack::VERSION,
|
|
19
|
+
"rack.input" => Rack::RewindableInput.new($stdin),
|
|
20
20
|
"rack.errors" => $stderr,
|
|
21
21
|
|
|
22
22
|
"rack.multithread" => false,
|
|
@@ -26,7 +26,7 @@ module Rack
|
|
|
26
26
|
"rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http"
|
|
27
27
|
})
|
|
28
28
|
|
|
29
|
-
env[
|
|
29
|
+
env[QUERY_STRING] ||= ""
|
|
30
30
|
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
|
|
31
31
|
env["REQUEST_PATH"] ||= "/"
|
|
32
32
|
|
|
@@ -40,20 +40,20 @@ module Rack
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def self.send_headers(status, headers)
|
|
43
|
-
|
|
43
|
+
$stdout.print "Status: #{status}\r\n"
|
|
44
44
|
headers.each { |k, vs|
|
|
45
45
|
vs.split("\n").each { |v|
|
|
46
|
-
|
|
46
|
+
$stdout.print "#{k}: #{v}\r\n"
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
$stdout.print "\r\n"
|
|
50
|
+
$stdout.flush
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def self.send_body(body)
|
|
54
54
|
body.each { |part|
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
$stdout.print part
|
|
56
|
+
$stdout.flush
|
|
57
57
|
}
|
|
58
58
|
end
|
|
59
59
|
end
|
data/lib/rack/handler/fastcgi.rb
CHANGED
|
@@ -19,16 +19,28 @@ module Rack
|
|
|
19
19
|
module Handler
|
|
20
20
|
class FastCGI
|
|
21
21
|
def self.run(app, options={})
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
if options[:File]
|
|
23
|
+
STDIN.reopen(UNIXServer.new(options[:File]))
|
|
24
|
+
elsif options[:Port]
|
|
25
|
+
STDIN.reopen(TCPServer.new(options[:Host], options[:Port]))
|
|
26
|
+
end
|
|
24
27
|
FCGI.each { |request|
|
|
25
28
|
serve request, app
|
|
26
29
|
}
|
|
27
30
|
end
|
|
28
31
|
|
|
29
|
-
def self.
|
|
30
|
-
|
|
32
|
+
def self.valid_options
|
|
33
|
+
environment = ENV['RACK_ENV'] || 'development'
|
|
34
|
+
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
|
35
|
+
|
|
36
|
+
{
|
|
37
|
+
"Host=HOST" => "Hostname to listen on (default: #{default_host})",
|
|
38
|
+
"Port=PORT" => "Port to listen on (default: 8080)",
|
|
39
|
+
"File=PATH" => "Creates a Domain socket at PATH instead of a TCP socket. Ignores Host and Port if set.",
|
|
40
|
+
}
|
|
41
|
+
end
|
|
31
42
|
|
|
43
|
+
def self.serve(request, app)
|
|
32
44
|
env = request.env
|
|
33
45
|
env.delete "HTTP_CONTENT_LENGTH"
|
|
34
46
|
|
|
@@ -36,7 +48,7 @@ module Rack
|
|
|
36
48
|
|
|
37
49
|
rack_input = RewindableInput.new(request.in)
|
|
38
50
|
|
|
39
|
-
env.update({"rack.version" =>
|
|
51
|
+
env.update({"rack.version" => Rack::VERSION,
|
|
40
52
|
"rack.input" => rack_input,
|
|
41
53
|
"rack.errors" => request.err,
|
|
42
54
|
|
|
@@ -47,7 +59,7 @@ module Rack
|
|
|
47
59
|
"rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
|
|
48
60
|
})
|
|
49
61
|
|
|
50
|
-
env[
|
|
62
|
+
env[QUERY_STRING] ||= ""
|
|
51
63
|
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
|
|
52
64
|
env["REQUEST_PATH"] ||= "/"
|
|
53
65
|
env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == ""
|
data/lib/rack/handler/lsws.rb
CHANGED
|
@@ -11,8 +11,6 @@ module Rack
|
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
def self.serve(app)
|
|
14
|
-
app = Rack::ContentLength.new(app)
|
|
15
|
-
|
|
16
14
|
env = ENV.to_hash
|
|
17
15
|
env.delete "HTTP_CONTENT_LENGTH"
|
|
18
16
|
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
|
|
@@ -20,7 +18,7 @@ module Rack
|
|
|
20
18
|
rack_input = RewindableInput.new($stdin.read.to_s)
|
|
21
19
|
|
|
22
20
|
env.update(
|
|
23
|
-
"rack.version" =>
|
|
21
|
+
"rack.version" => Rack::VERSION,
|
|
24
22
|
"rack.input" => rack_input,
|
|
25
23
|
"rack.errors" => $stderr,
|
|
26
24
|
"rack.multithread" => false,
|
|
@@ -29,7 +27,7 @@ module Rack
|
|
|
29
27
|
"rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http"
|
|
30
28
|
)
|
|
31
29
|
|
|
32
|
-
env[
|
|
30
|
+
env[QUERY_STRING] ||= ""
|
|
33
31
|
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
|
|
34
32
|
env["REQUEST_PATH"] ||= "/"
|
|
35
33
|
status, headers, body = app.call(env)
|
data/lib/rack/handler/mongrel.rb
CHANGED
|
@@ -7,8 +7,11 @@ module Rack
|
|
|
7
7
|
module Handler
|
|
8
8
|
class Mongrel < ::Mongrel::HttpHandler
|
|
9
9
|
def self.run(app, options={})
|
|
10
|
+
environment = ENV['RACK_ENV'] || 'development'
|
|
11
|
+
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
|
12
|
+
|
|
10
13
|
server = ::Mongrel::HttpServer.new(
|
|
11
|
-
options[:Host] ||
|
|
14
|
+
options[:Host] || default_host,
|
|
12
15
|
options[:Port] || 8080,
|
|
13
16
|
options[:num_processors] || 950,
|
|
14
17
|
options[:throttle] || 0,
|
|
@@ -38,12 +41,25 @@ module Rack
|
|
|
38
41
|
server.run.join
|
|
39
42
|
end
|
|
40
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
|
+
"Processors=N" => "Number of concurrent processors to accept (default: 950)",
|
|
52
|
+
"Timeout=N" => "Time before a request is dropped for inactivity (default: 60)",
|
|
53
|
+
"Throttle=N" => "Throttle time between socket.accept calls in hundredths of a second (default: 0)",
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
|
|
41
57
|
def initialize(app)
|
|
42
|
-
@app =
|
|
58
|
+
@app = app
|
|
43
59
|
end
|
|
44
60
|
|
|
45
61
|
def process(request, response)
|
|
46
|
-
env =
|
|
62
|
+
env = Hash[request.params]
|
|
47
63
|
env.delete "HTTP_CONTENT_TYPE"
|
|
48
64
|
env.delete "HTTP_CONTENT_LENGTH"
|
|
49
65
|
|
|
@@ -52,7 +68,7 @@ module Rack
|
|
|
52
68
|
rack_input = request.body || StringIO.new('')
|
|
53
69
|
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
|
|
54
70
|
|
|
55
|
-
env.update({"rack.version" =>
|
|
71
|
+
env.update({"rack.version" => Rack::VERSION,
|
|
56
72
|
"rack.input" => rack_input,
|
|
57
73
|
"rack.errors" => $stderr,
|
|
58
74
|
|
|
@@ -60,9 +76,9 @@ module Rack
|
|
|
60
76
|
"rack.multiprocess" => false, # ???
|
|
61
77
|
"rack.run_once" => false,
|
|
62
78
|
|
|
63
|
-
"rack.url_scheme" => "http"
|
|
79
|
+
"rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
|
|
64
80
|
})
|
|
65
|
-
env[
|
|
81
|
+
env[QUERY_STRING] ||= ""
|
|
66
82
|
|
|
67
83
|
status, headers, body = @app.call(env)
|
|
68
84
|
|
data/lib/rack/handler/scgi.rb
CHANGED
|
@@ -9,34 +9,42 @@ module Rack
|
|
|
9
9
|
attr_accessor :app
|
|
10
10
|
|
|
11
11
|
def self.run(app, options=nil)
|
|
12
|
+
options[:Socket] = UNIXServer.new(options[:File]) if options[:File]
|
|
12
13
|
new(options.merge(:app=>app,
|
|
13
14
|
:host=>options[:Host],
|
|
14
15
|
:port=>options[:Port],
|
|
15
16
|
:socket=>options[:Socket])).listen
|
|
16
17
|
end
|
|
17
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
|
+
|
|
18
29
|
def initialize(settings = {})
|
|
19
|
-
@app =
|
|
20
|
-
@log = Object.new
|
|
21
|
-
def @log.info(*args); end
|
|
22
|
-
def @log.error(*args); end
|
|
30
|
+
@app = settings[:app]
|
|
23
31
|
super(settings)
|
|
24
32
|
end
|
|
25
33
|
|
|
26
34
|
def process_request(request, input_body, socket)
|
|
27
|
-
env =
|
|
35
|
+
env = Hash[request]
|
|
28
36
|
env.delete "HTTP_CONTENT_TYPE"
|
|
29
37
|
env.delete "HTTP_CONTENT_LENGTH"
|
|
30
|
-
env["REQUEST_PATH"], env[
|
|
38
|
+
env["REQUEST_PATH"], env[QUERY_STRING] = env["REQUEST_URI"].split('?', 2)
|
|
31
39
|
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
|
|
32
|
-
env[
|
|
40
|
+
env[PATH_INFO] = env["REQUEST_PATH"]
|
|
33
41
|
env["QUERY_STRING"] ||= ""
|
|
34
42
|
env["SCRIPT_NAME"] = ""
|
|
35
43
|
|
|
36
44
|
rack_input = StringIO.new(input_body)
|
|
37
45
|
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
|
|
38
46
|
|
|
39
|
-
env.update({"rack.version" =>
|
|
47
|
+
env.update({"rack.version" => Rack::VERSION,
|
|
40
48
|
"rack.input" => rack_input,
|
|
41
49
|
"rack.errors" => $stderr,
|
|
42
50
|
"rack.multithread" => true,
|
data/lib/rack/handler/thin.rb
CHANGED
|
@@ -6,13 +6,28 @@ module Rack
|
|
|
6
6
|
module Handler
|
|
7
7
|
class Thin
|
|
8
8
|
def self.run(app, options={})
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
environment = ENV['RACK_ENV'] || 'development'
|
|
10
|
+
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
|
11
|
+
|
|
12
|
+
host = options.delete(:Host) || default_host
|
|
13
|
+
port = options.delete(:Port) || 8080
|
|
14
|
+
args = [host, port, app, options]
|
|
15
|
+
# Thin versions below 0.8.0 do not support additional options
|
|
16
|
+
args.pop if ::Thin::VERSION::MAJOR < 1 && ::Thin::VERSION::MINOR < 8
|
|
17
|
+
server = ::Thin::Server.new(*args)
|
|
13
18
|
yield server if block_given?
|
|
14
19
|
server.start
|
|
15
20
|
end
|
|
21
|
+
|
|
22
|
+
def self.valid_options
|
|
23
|
+
environment = ENV['RACK_ENV'] || 'development'
|
|
24
|
+
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
|
25
|
+
|
|
26
|
+
{
|
|
27
|
+
"Host=HOST" => "Hostname to listen on (default: #{default_host})",
|
|
28
|
+
"Port=PORT" => "Port to listen on (default: 8080)",
|
|
29
|
+
}
|
|
30
|
+
end
|
|
16
31
|
end
|
|
17
32
|
end
|
|
18
33
|
end
|
data/lib/rack/handler/webrick.rb
CHANGED
|
@@ -2,31 +2,67 @@ require 'webrick'
|
|
|
2
2
|
require 'stringio'
|
|
3
3
|
require 'rack/content_length'
|
|
4
4
|
|
|
5
|
+
# This monkey patch allows for applications to perform their own chunking
|
|
6
|
+
# through WEBrick::HTTPResponse iff rack is set to true.
|
|
7
|
+
class WEBrick::HTTPResponse
|
|
8
|
+
attr_accessor :rack
|
|
9
|
+
|
|
10
|
+
alias _rack_setup_header setup_header
|
|
11
|
+
def setup_header
|
|
12
|
+
app_chunking = rack && @header['transfer-encoding'] == 'chunked'
|
|
13
|
+
|
|
14
|
+
@chunked = app_chunking if app_chunking
|
|
15
|
+
|
|
16
|
+
_rack_setup_header
|
|
17
|
+
|
|
18
|
+
@chunked = false if app_chunking
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
5
22
|
module Rack
|
|
6
23
|
module Handler
|
|
7
24
|
class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet
|
|
8
25
|
def self.run(app, options={})
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
server.
|
|
26
|
+
environment = ENV['RACK_ENV'] || 'development'
|
|
27
|
+
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
|
28
|
+
|
|
29
|
+
options[:BindAddress] = options.delete(:Host) || default_host
|
|
30
|
+
options[:Port] ||= 8080
|
|
31
|
+
@server = ::WEBrick::HTTPServer.new(options)
|
|
32
|
+
@server.mount "/", Rack::Handler::WEBrick, app
|
|
33
|
+
yield @server if block_given?
|
|
34
|
+
@server.start
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.valid_options
|
|
38
|
+
environment = ENV['RACK_ENV'] || 'development'
|
|
39
|
+
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
|
40
|
+
|
|
41
|
+
{
|
|
42
|
+
"Host=HOST" => "Hostname to listen on (default: #{default_host})",
|
|
43
|
+
"Port=PORT" => "Port to listen on (default: 8080)",
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.shutdown
|
|
48
|
+
@server.shutdown
|
|
49
|
+
@server = nil
|
|
15
50
|
end
|
|
16
51
|
|
|
17
52
|
def initialize(server, app)
|
|
18
53
|
super server
|
|
19
|
-
@app =
|
|
54
|
+
@app = app
|
|
20
55
|
end
|
|
21
56
|
|
|
22
57
|
def service(req, res)
|
|
58
|
+
res.rack = true
|
|
23
59
|
env = req.meta_vars
|
|
24
60
|
env.delete_if { |k, v| v.nil? }
|
|
25
61
|
|
|
26
62
|
rack_input = StringIO.new(req.body.to_s)
|
|
27
63
|
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
|
|
28
64
|
|
|
29
|
-
env.update({"rack.version" =>
|
|
65
|
+
env.update({"rack.version" => Rack::VERSION,
|
|
30
66
|
"rack.input" => rack_input,
|
|
31
67
|
"rack.errors" => $stderr,
|
|
32
68
|
|
|
@@ -34,32 +70,49 @@ module Rack
|
|
|
34
70
|
"rack.multiprocess" => false,
|
|
35
71
|
"rack.run_once" => false,
|
|
36
72
|
|
|
37
|
-
"rack.url_scheme" => ["yes", "on", "1"].include?(
|
|
73
|
+
"rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http",
|
|
74
|
+
|
|
75
|
+
"rack.hijack?" => true,
|
|
76
|
+
"rack.hijack" => lambda { raise NotImplementedError, "only partial hijack is supported."},
|
|
77
|
+
"rack.hijack_io" => nil,
|
|
38
78
|
})
|
|
39
79
|
|
|
40
80
|
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
|
|
41
|
-
env[
|
|
42
|
-
env[
|
|
43
|
-
unless env["PATH_INFO"] == ""
|
|
81
|
+
env[QUERY_STRING] ||= ""
|
|
82
|
+
unless env[PATH_INFO] == ""
|
|
44
83
|
path, n = req.request_uri.path, env["SCRIPT_NAME"].length
|
|
45
|
-
env[
|
|
84
|
+
env[PATH_INFO] = path[n, path.length-n]
|
|
46
85
|
end
|
|
86
|
+
env["REQUEST_PATH"] ||= [env["SCRIPT_NAME"], env[PATH_INFO]].join
|
|
47
87
|
|
|
48
88
|
status, headers, body = @app.call(env)
|
|
49
89
|
begin
|
|
50
90
|
res.status = status.to_i
|
|
51
91
|
headers.each { |k, vs|
|
|
92
|
+
next if k.downcase == "rack.hijack"
|
|
93
|
+
|
|
52
94
|
if k.downcase == "set-cookie"
|
|
53
95
|
res.cookies.concat vs.split("\n")
|
|
54
96
|
else
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
97
|
+
# Since WEBrick won't accept repeated headers,
|
|
98
|
+
# merge the values per RFC 1945 section 4.2.
|
|
99
|
+
res[k] = vs.split("\n").join(", ")
|
|
58
100
|
end
|
|
59
101
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
102
|
+
|
|
103
|
+
io_lambda = headers["rack.hijack"]
|
|
104
|
+
if io_lambda
|
|
105
|
+
rd, wr = IO.pipe
|
|
106
|
+
res.body = rd
|
|
107
|
+
res.chunked = true
|
|
108
|
+
io_lambda.call wr
|
|
109
|
+
elsif body.respond_to?(:to_path)
|
|
110
|
+
res.body = ::File.open(body.to_path, 'rb')
|
|
111
|
+
else
|
|
112
|
+
body.each { |part|
|
|
113
|
+
res.body << part
|
|
114
|
+
}
|
|
115
|
+
end
|
|
63
116
|
ensure
|
|
64
117
|
body.close if body.respond_to? :close
|
|
65
118
|
end
|
data/lib/rack/handler.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Rack
|
|
2
2
|
# *Handlers* connect web servers with Rack.
|
|
3
3
|
#
|
|
4
|
-
# Rack includes Handlers for
|
|
4
|
+
# Rack includes Handlers for Thin, WEBrick, FastCGI, CGI, SCGI
|
|
5
5
|
# and LiteSpeed.
|
|
6
6
|
#
|
|
7
7
|
# Handlers usually are activated by calling <tt>MyHandler.run(myapp)</tt>.
|
|
@@ -12,14 +12,47 @@ module Rack
|
|
|
12
12
|
return unless server
|
|
13
13
|
server = server.to_s
|
|
14
14
|
|
|
15
|
+
unless @handlers.include? server
|
|
16
|
+
load_error = try_require('rack/handler', server)
|
|
17
|
+
end
|
|
18
|
+
|
|
15
19
|
if klass = @handlers[server]
|
|
16
|
-
|
|
17
|
-
klass.split("::").each { |x| obj = obj.const_get(x) }
|
|
18
|
-
obj
|
|
20
|
+
klass.split("::").inject(Object) { |o, x| o.const_get(x) }
|
|
19
21
|
else
|
|
20
|
-
|
|
21
|
-
const_get(server)
|
|
22
|
+
_const_get(server, false)
|
|
22
23
|
end
|
|
24
|
+
|
|
25
|
+
rescue NameError => name_error
|
|
26
|
+
raise load_error || name_error
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
begin
|
|
30
|
+
::Object.const_get("Object", false)
|
|
31
|
+
def self._const_get(str, inherit = true)
|
|
32
|
+
const_get(str, inherit)
|
|
33
|
+
end
|
|
34
|
+
rescue
|
|
35
|
+
def self._const_get(str, inherit = true)
|
|
36
|
+
const_get(str)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# Select first available Rack handler given an `Array` of server names.
|
|
42
|
+
# Raises `LoadError` if no handler was found.
|
|
43
|
+
#
|
|
44
|
+
# > pick ['thin', 'webrick']
|
|
45
|
+
# => Rack::Handler::WEBrick
|
|
46
|
+
def self.pick(server_names)
|
|
47
|
+
server_names = Array(server_names)
|
|
48
|
+
server_names.each do |server_name|
|
|
49
|
+
begin
|
|
50
|
+
return get(server_name.to_s)
|
|
51
|
+
rescue LoadError, NameError
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
raise LoadError, "Couldn't find handler for: #{server_names.join(', ')}."
|
|
23
56
|
end
|
|
24
57
|
|
|
25
58
|
def self.default(options = {})
|
|
@@ -30,14 +63,12 @@ module Rack
|
|
|
30
63
|
options.delete :Port
|
|
31
64
|
|
|
32
65
|
Rack::Handler::FastCGI
|
|
33
|
-
elsif ENV.include?(
|
|
66
|
+
elsif ENV.include?(REQUEST_METHOD)
|
|
34
67
|
Rack::Handler::CGI
|
|
68
|
+
elsif ENV.include?("RACK_HANDLER")
|
|
69
|
+
self.get(ENV["RACK_HANDLER"])
|
|
35
70
|
else
|
|
36
|
-
|
|
37
|
-
Rack::Handler::Mongrel
|
|
38
|
-
rescue LoadError => e
|
|
39
|
-
Rack::Handler::WEBrick
|
|
40
|
-
end
|
|
71
|
+
pick ['thin', 'puma', 'webrick']
|
|
41
72
|
end
|
|
42
73
|
end
|
|
43
74
|
|
|
@@ -57,12 +88,14 @@ module Rack
|
|
|
57
88
|
gsub(/[A-Z]+[^A-Z]/, '_\&').downcase
|
|
58
89
|
|
|
59
90
|
require(::File.join(prefix, file))
|
|
60
|
-
|
|
91
|
+
nil
|
|
92
|
+
rescue LoadError => error
|
|
93
|
+
error
|
|
61
94
|
end
|
|
62
95
|
|
|
63
96
|
def self.register(server, klass)
|
|
64
97
|
@handlers ||= {}
|
|
65
|
-
@handlers[server] = klass
|
|
98
|
+
@handlers[server.to_s] = klass.to_s
|
|
66
99
|
end
|
|
67
100
|
|
|
68
101
|
autoload :CGI, "rack/handler/cgi"
|
data/lib/rack/head.rb
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
require 'rack/body_proxy'
|
|
2
|
+
|
|
1
3
|
module Rack
|
|
2
4
|
|
|
3
5
|
class Head
|
|
6
|
+
# Rack::Head returns an empty body for all HEAD requests. It leaves
|
|
7
|
+
# all other requests unchanged.
|
|
4
8
|
def initialize(app)
|
|
5
9
|
@app = app
|
|
6
10
|
end
|
|
@@ -8,8 +12,12 @@ class Head
|
|
|
8
12
|
def call(env)
|
|
9
13
|
status, headers, body = @app.call(env)
|
|
10
14
|
|
|
11
|
-
if env[
|
|
12
|
-
[
|
|
15
|
+
if env[REQUEST_METHOD] == HEAD
|
|
16
|
+
[
|
|
17
|
+
status, headers, Rack::BodyProxy.new([]) do
|
|
18
|
+
body.close if body.respond_to? :close
|
|
19
|
+
end
|
|
20
|
+
]
|
|
13
21
|
else
|
|
14
22
|
[status, headers, body]
|
|
15
23
|
end
|