rack 1.6.11 → 2.2.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 +675 -0
- data/CONTRIBUTING.md +136 -0
- data/{COPYING → MIT-LICENSE} +4 -2
- data/README.rdoc +157 -163
- data/Rakefile +38 -32
- data/{SPEC → SPEC.rdoc} +41 -13
- data/bin/rackup +1 -0
- data/contrib/rack_logo.svg +164 -111
- data/example/lobster.ru +2 -0
- data/example/protectedlobster.rb +4 -2
- data/example/protectedlobster.ru +3 -1
- data/lib/rack/auth/abstract/handler.rb +3 -1
- data/lib/rack/auth/abstract/request.rb +6 -2
- 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 +5 -4
- data/lib/rack/auth/digest/request.rb +6 -4
- data/lib/rack/body_proxy.rb +21 -15
- data/lib/rack/builder.rb +119 -26
- data/lib/rack/cascade.rb +28 -12
- data/lib/rack/chunked.rb +70 -22
- data/lib/rack/common_logger.rb +80 -0
- data/lib/rack/{conditionalget.rb → conditional_get.rb} +20 -16
- data/lib/rack/config.rb +2 -0
- data/lib/rack/content_length.rb +9 -8
- data/lib/rack/content_type.rb +5 -4
- data/lib/rack/core_ext/regexp.rb +14 -0
- data/lib/rack/deflater.rb +60 -70
- data/lib/rack/directory.rb +117 -85
- data/lib/rack/etag.rb +9 -7
- data/lib/rack/events.rb +153 -0
- data/lib/rack/file.rb +4 -149
- data/lib/rack/files.rb +218 -0
- data/lib/rack/handler/cgi.rb +17 -19
- data/lib/rack/handler/fastcgi.rb +17 -18
- data/lib/rack/handler/lsws.rb +14 -14
- data/lib/rack/handler/scgi.rb +22 -21
- data/lib/rack/handler/thin.rb +20 -11
- data/lib/rack/handler/webrick.rb +39 -32
- data/lib/rack/handler.rb +9 -26
- data/lib/rack/head.rb +16 -18
- data/lib/rack/lint.rb +110 -64
- data/lib/rack/lobster.rb +10 -10
- data/lib/rack/lock.rb +17 -11
- data/lib/rack/logger.rb +4 -2
- data/lib/rack/media_type.rb +43 -0
- data/lib/rack/{methodoverride.rb → method_override.rb} +10 -8
- data/lib/rack/mime.rb +27 -6
- data/lib/rack/mock.rb +124 -65
- data/lib/rack/multipart/generator.rb +20 -16
- data/lib/rack/multipart/parser.rb +273 -162
- data/lib/rack/multipart/uploaded_file.rb +15 -8
- data/lib/rack/multipart.rb +39 -8
- data/lib/rack/{nulllogger.rb → null_logger.rb} +3 -1
- data/lib/rack/query_parser.rb +217 -0
- data/lib/rack/recursive.rb +11 -9
- data/lib/rack/reloader.rb +8 -4
- data/lib/rack/request.rb +543 -305
- data/lib/rack/response.rb +244 -88
- data/lib/rack/rewindable_input.rb +5 -15
- data/lib/rack/runtime.rb +12 -18
- data/lib/rack/sendfile.rb +17 -15
- data/lib/rack/server.rb +125 -47
- data/lib/rack/session/abstract/id.rb +216 -93
- data/lib/rack/session/cookie.rb +47 -31
- data/lib/rack/session/memcache.rb +4 -87
- data/lib/rack/session/pool.rb +26 -17
- data/lib/rack/show_exceptions.rb +390 -0
- data/lib/rack/{showstatus.rb → show_status.rb} +8 -8
- data/lib/rack/static.rb +48 -11
- data/lib/rack/tempfile_reaper.rb +3 -3
- data/lib/rack/urlmap.rb +26 -19
- data/lib/rack/utils.rb +208 -294
- data/lib/rack/version.rb +29 -0
- data/lib/rack.rb +76 -33
- data/rack.gemspec +43 -30
- metadata +62 -183
- data/HISTORY.md +0 -375
- data/KNOWN-ISSUES +0 -44
- data/lib/rack/backports/uri/common_18.rb +0 -56
- data/lib/rack/backports/uri/common_192.rb +0 -52
- data/lib/rack/backports/uri/common_193.rb +0 -29
- data/lib/rack/commonlogger.rb +0 -72
- data/lib/rack/handler/evented_mongrel.rb +0 -8
- data/lib/rack/handler/mongrel.rb +0 -106
- data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
- data/lib/rack/showexceptions.rb +0 -387
- data/lib/rack/utils/okjson.rb +0 -600
- 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 -8
- data/test/cgi/test.ru +0 -5
- data/test/gemloader.rb +0 -10
- 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_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_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/semicolon +0 -6
- data/test/multipart/text +0 -15
- data/test/multipart/three_files_three_fields +0 -31
- 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 -81
- data/test/spec_auth_digest.rb +0 -259
- data/test/spec_body_proxy.rb +0 -85
- data/test/spec_builder.rb +0 -223
- data/test/spec_cascade.rb +0 -61
- data/test/spec_cgi.rb +0 -102
- data/test/spec_chunked.rb +0 -101
- data/test/spec_commonlogger.rb +0 -93
- data/test/spec_conditionalget.rb +0 -102
- data/test/spec_config.rb +0 -22
- data/test/spec_content_length.rb +0 -85
- data/test/spec_content_type.rb +0 -45
- data/test/spec_deflater.rb +0 -339
- data/test/spec_directory.rb +0 -88
- data/test/spec_etag.rb +0 -107
- data/test/spec_fastcgi.rb +0 -107
- data/test/spec_file.rb +0 -221
- data/test/spec_handler.rb +0 -72
- data/test/spec_head.rb +0 -45
- data/test/spec_lint.rb +0 -550
- data/test/spec_lobster.rb +0 -58
- data/test/spec_lock.rb +0 -164
- data/test/spec_logger.rb +0 -23
- data/test/spec_methodoverride.rb +0 -111
- data/test/spec_mime.rb +0 -51
- data/test/spec_mock.rb +0 -297
- data/test/spec_mongrel.rb +0 -182
- data/test/spec_multipart.rb +0 -600
- data/test/spec_nulllogger.rb +0 -20
- data/test/spec_recursive.rb +0 -72
- data/test/spec_request.rb +0 -1232
- data/test/spec_response.rb +0 -407
- data/test/spec_rewindable_input.rb +0 -118
- data/test/spec_runtime.rb +0 -49
- data/test/spec_sendfile.rb +0 -130
- data/test/spec_server.rb +0 -167
- data/test/spec_session_abstract_id.rb +0 -53
- data/test/spec_session_cookie.rb +0 -410
- data/test/spec_session_memcache.rb +0 -321
- data/test/spec_session_pool.rb +0 -209
- data/test/spec_showexceptions.rb +0 -98
- data/test/spec_showstatus.rb +0 -103
- data/test/spec_static.rb +0 -145
- data/test/spec_tempfile_reaper.rb +0 -63
- data/test/spec_thin.rb +0 -91
- data/test/spec_urlmap.rb +0 -236
- data/test/spec_utils.rb +0 -647
- data/test/spec_version.rb +0 -17
- data/test/spec_webrick.rb +0 -184
- data/test/static/another/index.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/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
|
@@ -35,24 +35,25 @@ module Rack
|
|
35
35
|
env = Hash[request]
|
36
36
|
env.delete "HTTP_CONTENT_TYPE"
|
37
37
|
env.delete "HTTP_CONTENT_LENGTH"
|
38
|
-
env[
|
39
|
-
env[
|
40
|
-
env[PATH_INFO] = env[
|
41
|
-
env[
|
42
|
-
env[
|
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
43
|
|
44
44
|
rack_input = StringIO.new(input_body)
|
45
|
-
rack_input.set_encoding(Encoding::BINARY)
|
45
|
+
rack_input.set_encoding(Encoding::BINARY)
|
46
46
|
|
47
|
-
env.update(
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
+
)
|
53
56
|
|
54
|
-
"rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
|
55
|
-
})
|
56
57
|
status, headers, body = app.call(env)
|
57
58
|
begin
|
58
59
|
socket.write("Status: #{status}\r\n")
|
data/lib/rack/handler/thin.rb
CHANGED
@@ -1,22 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "thin"
|
2
|
-
require "
|
3
|
-
require "
|
4
|
+
require "thin/server"
|
5
|
+
require "thin/logging"
|
6
|
+
require "thin/backends/tcp_server"
|
4
7
|
|
5
8
|
module Rack
|
6
9
|
module Handler
|
7
10
|
class Thin
|
8
|
-
def self.run(app, options
|
11
|
+
def self.run(app, **options)
|
9
12
|
environment = ENV['RACK_ENV'] || 'development'
|
10
13
|
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
if block_given?
|
16
|
+
host = options.delete(:Host) || default_host
|
17
|
+
port = options.delete(:Port) || 8080
|
18
|
+
args = [host, port, app, options]
|
19
|
+
# Thin versions below 0.8.0 do not support additional options
|
20
|
+
args.pop if ::Thin::VERSION::MAJOR < 1 && ::Thin::VERSION::MINOR < 8
|
21
|
+
server = ::Thin::Server.new(*args)
|
22
|
+
yield server
|
23
|
+
server.start
|
24
|
+
else
|
25
|
+
options[:address] = options[:Host] || default_host
|
26
|
+
options[:port] = options[:Port] || 8080
|
27
|
+
::Thin::Controllers::Controller.new(options).start
|
28
|
+
end
|
20
29
|
end
|
21
30
|
|
22
31
|
def self.valid_options
|
data/lib/rack/handler/webrick.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
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
|
-
# through WEBrick::HTTPResponse
|
7
|
+
# through WEBrick::HTTPResponse if rack is set to true.
|
7
8
|
class WEBrick::HTTPResponse
|
8
9
|
attr_accessor :rack
|
9
10
|
|
@@ -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
|
-
default_host = environment == 'development' ? 'localhost' :
|
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)
|
@@ -60,38 +69,37 @@ module Rack
|
|
60
69
|
env.delete_if { |k, v| v.nil? }
|
61
70
|
|
62
71
|
rack_input = StringIO.new(req.body.to_s)
|
63
|
-
rack_input.set_encoding(Encoding::BINARY)
|
64
|
-
|
65
|
-
env.update(
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
|
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]
|
81
88
|
env[QUERY_STRING] ||= ""
|
82
89
|
unless env[PATH_INFO] == ""
|
83
|
-
path, n = req.request_uri.path, env[
|
84
|
-
env[PATH_INFO] = path[n, path.length-n]
|
90
|
+
path, n = req.request_uri.path, env[SCRIPT_NAME].length
|
91
|
+
env[PATH_INFO] = path[n, path.length - n]
|
85
92
|
end
|
86
|
-
env[
|
93
|
+
env[REQUEST_PATH] ||= [env[SCRIPT_NAME], env[PATH_INFO]].join
|
87
94
|
|
88
95
|
status, headers, body = @app.call(env)
|
89
96
|
begin
|
90
97
|
res.status = status.to_i
|
98
|
+
io_lambda = nil
|
91
99
|
headers.each { |k, vs|
|
92
|
-
|
93
|
-
|
94
|
-
|
100
|
+
if k == RACK_HIJACK
|
101
|
+
io_lambda = vs
|
102
|
+
elsif k.downcase == "set-cookie"
|
95
103
|
res.cookies.concat vs.split("\n")
|
96
104
|
else
|
97
105
|
# Since WEBrick won't accept repeated headers,
|
@@ -100,7 +108,6 @@ module Rack
|
|
100
108
|
end
|
101
109
|
}
|
102
110
|
|
103
|
-
io_lambda = headers["rack.hijack"]
|
104
111
|
if io_lambda
|
105
112
|
rd, wr = IO.pipe
|
106
113
|
res.body = rd
|
data/lib/rack/handler.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rack
|
2
4
|
# *Handlers* connect web servers with Rack.
|
3
5
|
#
|
@@ -17,27 +19,15 @@ module Rack
|
|
17
19
|
end
|
18
20
|
|
19
21
|
if klass = @handlers[server]
|
20
|
-
|
22
|
+
const_get(klass)
|
21
23
|
else
|
22
|
-
|
24
|
+
const_get(server, false)
|
23
25
|
end
|
24
26
|
|
25
27
|
rescue NameError => name_error
|
26
28
|
raise load_error || name_error
|
27
29
|
end
|
28
30
|
|
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
31
|
# Select first available Rack handler given an `Array` of server names.
|
42
32
|
# Raises `LoadError` if no handler was found.
|
43
33
|
#
|
@@ -55,20 +45,19 @@ module Rack
|
|
55
45
|
raise LoadError, "Couldn't find handler for: #{server_names.join(', ')}."
|
56
46
|
end
|
57
47
|
|
58
|
-
|
48
|
+
SERVER_NAMES = %w(puma thin falcon webrick).freeze
|
49
|
+
private_constant :SERVER_NAMES
|
50
|
+
|
51
|
+
def self.default
|
59
52
|
# Guess.
|
60
53
|
if ENV.include?("PHP_FCGI_CHILDREN")
|
61
|
-
# We already speak FastCGI
|
62
|
-
options.delete :File
|
63
|
-
options.delete :Port
|
64
|
-
|
65
54
|
Rack::Handler::FastCGI
|
66
55
|
elsif ENV.include?(REQUEST_METHOD)
|
67
56
|
Rack::Handler::CGI
|
68
57
|
elsif ENV.include?("RACK_HANDLER")
|
69
58
|
self.get(ENV["RACK_HANDLER"])
|
70
59
|
else
|
71
|
-
pick
|
60
|
+
pick SERVER_NAMES
|
72
61
|
end
|
73
62
|
end
|
74
63
|
|
@@ -100,9 +89,6 @@ module Rack
|
|
100
89
|
|
101
90
|
autoload :CGI, "rack/handler/cgi"
|
102
91
|
autoload :FastCGI, "rack/handler/fastcgi"
|
103
|
-
autoload :Mongrel, "rack/handler/mongrel"
|
104
|
-
autoload :EventedMongrel, "rack/handler/evented_mongrel"
|
105
|
-
autoload :SwiftipliedMongrel, "rack/handler/swiftiplied_mongrel"
|
106
92
|
autoload :WEBrick, "rack/handler/webrick"
|
107
93
|
autoload :LSWS, "rack/handler/lsws"
|
108
94
|
autoload :SCGI, "rack/handler/scgi"
|
@@ -110,9 +96,6 @@ module Rack
|
|
110
96
|
|
111
97
|
register 'cgi', 'Rack::Handler::CGI'
|
112
98
|
register 'fastcgi', 'Rack::Handler::FastCGI'
|
113
|
-
register 'mongrel', 'Rack::Handler::Mongrel'
|
114
|
-
register 'emongrel', 'Rack::Handler::EventedMongrel'
|
115
|
-
register 'smongrel', 'Rack::Handler::SwiftipliedMongrel'
|
116
99
|
register 'webrick', 'Rack::Handler::WEBrick'
|
117
100
|
register 'lsws', 'Rack::Handler::LSWS'
|
118
101
|
register 'scgi', 'Rack::Handler::SCGI'
|
data/lib/rack/head.rb
CHANGED
@@ -1,27 +1,25 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Rack
|
4
|
-
|
5
|
-
class Head
|
6
4
|
# Rack::Head returns an empty body for all HEAD requests. It leaves
|
7
5
|
# all other requests unchanged.
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
class Head
|
7
|
+
def initialize(app)
|
8
|
+
@app = app
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
def call(env)
|
12
|
+
status, headers, body = @app.call(env)
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
if env[REQUEST_METHOD] == HEAD
|
15
|
+
[
|
16
|
+
status, headers, Rack::BodyProxy.new([]) do
|
17
|
+
body.close if body.respond_to? :close
|
18
|
+
end
|
19
|
+
]
|
20
|
+
else
|
21
|
+
[status, headers, body]
|
22
|
+
end
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
27
|
-
end
|