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.

Files changed (190) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +675 -0
  3. data/CONTRIBUTING.md +136 -0
  4. data/{COPYING → MIT-LICENSE} +4 -2
  5. data/README.rdoc +157 -163
  6. data/Rakefile +38 -32
  7. data/{SPEC → SPEC.rdoc} +41 -13
  8. data/bin/rackup +1 -0
  9. data/contrib/rack_logo.svg +164 -111
  10. data/example/lobster.ru +2 -0
  11. data/example/protectedlobster.rb +4 -2
  12. data/example/protectedlobster.ru +3 -1
  13. data/lib/rack/auth/abstract/handler.rb +3 -1
  14. data/lib/rack/auth/abstract/request.rb +6 -2
  15. data/lib/rack/auth/basic.rb +7 -4
  16. data/lib/rack/auth/digest/md5.rb +13 -11
  17. data/lib/rack/auth/digest/nonce.rb +6 -3
  18. data/lib/rack/auth/digest/params.rb +5 -4
  19. data/lib/rack/auth/digest/request.rb +6 -4
  20. data/lib/rack/body_proxy.rb +21 -15
  21. data/lib/rack/builder.rb +119 -26
  22. data/lib/rack/cascade.rb +28 -12
  23. data/lib/rack/chunked.rb +70 -22
  24. data/lib/rack/common_logger.rb +80 -0
  25. data/lib/rack/{conditionalget.rb → conditional_get.rb} +20 -16
  26. data/lib/rack/config.rb +2 -0
  27. data/lib/rack/content_length.rb +9 -8
  28. data/lib/rack/content_type.rb +5 -4
  29. data/lib/rack/core_ext/regexp.rb +14 -0
  30. data/lib/rack/deflater.rb +60 -70
  31. data/lib/rack/directory.rb +117 -85
  32. data/lib/rack/etag.rb +9 -7
  33. data/lib/rack/events.rb +153 -0
  34. data/lib/rack/file.rb +4 -149
  35. data/lib/rack/files.rb +218 -0
  36. data/lib/rack/handler/cgi.rb +17 -19
  37. data/lib/rack/handler/fastcgi.rb +17 -18
  38. data/lib/rack/handler/lsws.rb +14 -14
  39. data/lib/rack/handler/scgi.rb +22 -21
  40. data/lib/rack/handler/thin.rb +20 -11
  41. data/lib/rack/handler/webrick.rb +39 -32
  42. data/lib/rack/handler.rb +9 -26
  43. data/lib/rack/head.rb +16 -18
  44. data/lib/rack/lint.rb +110 -64
  45. data/lib/rack/lobster.rb +10 -10
  46. data/lib/rack/lock.rb +17 -11
  47. data/lib/rack/logger.rb +4 -2
  48. data/lib/rack/media_type.rb +43 -0
  49. data/lib/rack/{methodoverride.rb → method_override.rb} +10 -8
  50. data/lib/rack/mime.rb +27 -6
  51. data/lib/rack/mock.rb +124 -65
  52. data/lib/rack/multipart/generator.rb +20 -16
  53. data/lib/rack/multipart/parser.rb +273 -162
  54. data/lib/rack/multipart/uploaded_file.rb +15 -8
  55. data/lib/rack/multipart.rb +39 -8
  56. data/lib/rack/{nulllogger.rb → null_logger.rb} +3 -1
  57. data/lib/rack/query_parser.rb +217 -0
  58. data/lib/rack/recursive.rb +11 -9
  59. data/lib/rack/reloader.rb +8 -4
  60. data/lib/rack/request.rb +543 -305
  61. data/lib/rack/response.rb +244 -88
  62. data/lib/rack/rewindable_input.rb +5 -15
  63. data/lib/rack/runtime.rb +12 -18
  64. data/lib/rack/sendfile.rb +17 -15
  65. data/lib/rack/server.rb +125 -47
  66. data/lib/rack/session/abstract/id.rb +216 -93
  67. data/lib/rack/session/cookie.rb +47 -31
  68. data/lib/rack/session/memcache.rb +4 -87
  69. data/lib/rack/session/pool.rb +26 -17
  70. data/lib/rack/show_exceptions.rb +390 -0
  71. data/lib/rack/{showstatus.rb → show_status.rb} +8 -8
  72. data/lib/rack/static.rb +48 -11
  73. data/lib/rack/tempfile_reaper.rb +3 -3
  74. data/lib/rack/urlmap.rb +26 -19
  75. data/lib/rack/utils.rb +208 -294
  76. data/lib/rack/version.rb +29 -0
  77. data/lib/rack.rb +76 -33
  78. data/rack.gemspec +43 -30
  79. metadata +62 -183
  80. data/HISTORY.md +0 -375
  81. data/KNOWN-ISSUES +0 -44
  82. data/lib/rack/backports/uri/common_18.rb +0 -56
  83. data/lib/rack/backports/uri/common_192.rb +0 -52
  84. data/lib/rack/backports/uri/common_193.rb +0 -29
  85. data/lib/rack/commonlogger.rb +0 -72
  86. data/lib/rack/handler/evented_mongrel.rb +0 -8
  87. data/lib/rack/handler/mongrel.rb +0 -106
  88. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  89. data/lib/rack/showexceptions.rb +0 -387
  90. data/lib/rack/utils/okjson.rb +0 -600
  91. data/test/builder/anything.rb +0 -5
  92. data/test/builder/comment.ru +0 -4
  93. data/test/builder/end.ru +0 -5
  94. data/test/builder/line.ru +0 -1
  95. data/test/builder/options.ru +0 -2
  96. data/test/cgi/assets/folder/test.js +0 -1
  97. data/test/cgi/assets/fonts/font.eot +0 -1
  98. data/test/cgi/assets/images/image.png +0 -1
  99. data/test/cgi/assets/index.html +0 -1
  100. data/test/cgi/assets/javascripts/app.js +0 -1
  101. data/test/cgi/assets/stylesheets/app.css +0 -1
  102. data/test/cgi/lighttpd.conf +0 -26
  103. data/test/cgi/rackup_stub.rb +0 -6
  104. data/test/cgi/sample_rackup.ru +0 -5
  105. data/test/cgi/test +0 -9
  106. data/test/cgi/test+directory/test+file +0 -1
  107. data/test/cgi/test.fcgi +0 -8
  108. data/test/cgi/test.ru +0 -5
  109. data/test/gemloader.rb +0 -10
  110. data/test/multipart/bad_robots +0 -259
  111. data/test/multipart/binary +0 -0
  112. data/test/multipart/content_type_and_no_filename +0 -6
  113. data/test/multipart/empty +0 -10
  114. data/test/multipart/fail_16384_nofile +0 -814
  115. data/test/multipart/file1.txt +0 -1
  116. data/test/multipart/filename_and_modification_param +0 -7
  117. data/test/multipart/filename_and_no_name +0 -6
  118. data/test/multipart/filename_with_escaped_quotes +0 -6
  119. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  120. data/test/multipart/filename_with_null_byte +0 -7
  121. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  122. data/test/multipart/filename_with_unescaped_percentages +0 -6
  123. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  124. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  125. data/test/multipart/filename_with_unescaped_quotes +0 -6
  126. data/test/multipart/ie +0 -6
  127. data/test/multipart/invalid_character +0 -6
  128. data/test/multipart/mixed_files +0 -21
  129. data/test/multipart/nested +0 -10
  130. data/test/multipart/none +0 -9
  131. data/test/multipart/semicolon +0 -6
  132. data/test/multipart/text +0 -15
  133. data/test/multipart/three_files_three_fields +0 -31
  134. data/test/multipart/webkit +0 -32
  135. data/test/rackup/config.ru +0 -31
  136. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  137. data/test/spec_auth_basic.rb +0 -81
  138. data/test/spec_auth_digest.rb +0 -259
  139. data/test/spec_body_proxy.rb +0 -85
  140. data/test/spec_builder.rb +0 -223
  141. data/test/spec_cascade.rb +0 -61
  142. data/test/spec_cgi.rb +0 -102
  143. data/test/spec_chunked.rb +0 -101
  144. data/test/spec_commonlogger.rb +0 -93
  145. data/test/spec_conditionalget.rb +0 -102
  146. data/test/spec_config.rb +0 -22
  147. data/test/spec_content_length.rb +0 -85
  148. data/test/spec_content_type.rb +0 -45
  149. data/test/spec_deflater.rb +0 -339
  150. data/test/spec_directory.rb +0 -88
  151. data/test/spec_etag.rb +0 -107
  152. data/test/spec_fastcgi.rb +0 -107
  153. data/test/spec_file.rb +0 -221
  154. data/test/spec_handler.rb +0 -72
  155. data/test/spec_head.rb +0 -45
  156. data/test/spec_lint.rb +0 -550
  157. data/test/spec_lobster.rb +0 -58
  158. data/test/spec_lock.rb +0 -164
  159. data/test/spec_logger.rb +0 -23
  160. data/test/spec_methodoverride.rb +0 -111
  161. data/test/spec_mime.rb +0 -51
  162. data/test/spec_mock.rb +0 -297
  163. data/test/spec_mongrel.rb +0 -182
  164. data/test/spec_multipart.rb +0 -600
  165. data/test/spec_nulllogger.rb +0 -20
  166. data/test/spec_recursive.rb +0 -72
  167. data/test/spec_request.rb +0 -1232
  168. data/test/spec_response.rb +0 -407
  169. data/test/spec_rewindable_input.rb +0 -118
  170. data/test/spec_runtime.rb +0 -49
  171. data/test/spec_sendfile.rb +0 -130
  172. data/test/spec_server.rb +0 -167
  173. data/test/spec_session_abstract_id.rb +0 -53
  174. data/test/spec_session_cookie.rb +0 -410
  175. data/test/spec_session_memcache.rb +0 -321
  176. data/test/spec_session_pool.rb +0 -209
  177. data/test/spec_showexceptions.rb +0 -98
  178. data/test/spec_showstatus.rb +0 -103
  179. data/test/spec_static.rb +0 -145
  180. data/test/spec_tempfile_reaper.rb +0 -63
  181. data/test/spec_thin.rb +0 -91
  182. data/test/spec_urlmap.rb +0 -236
  183. data/test/spec_utils.rb +0 -647
  184. data/test/spec_version.rb +0 -17
  185. data/test/spec_webrick.rb +0 -184
  186. data/test/static/another/index.html +0 -1
  187. data/test/static/index.html +0 -1
  188. data/test/testrequest.rb +0 -78
  189. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  190. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -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=nil)
11
+ def self.run(app, **options)
12
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
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["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"] = ""
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) if rack_input.respond_to?(:set_encoding)
45
+ rack_input.set_encoding(Encoding::BINARY)
46
46
 
47
- env.update({"rack.version" => Rack::VERSION,
48
- "rack.input" => rack_input,
49
- "rack.errors" => $stderr,
50
- "rack.multithread" => true,
51
- "rack.multiprocess" => true,
52
- "rack.run_once" => false,
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")
@@ -1,22 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "thin"
2
- require "rack/content_length"
3
- require "rack/chunked"
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
- 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)
18
- yield server if block_given?
19
- server.start
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
@@ -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 iff rack is set to true.
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' : '0.0.0.0'
28
+ default_host = environment == 'development' ? 'localhost' : nil
28
29
 
29
- options[:BindAddress] = options.delete(:Host) || default_host
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.shutdown
49
- @server = nil
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) if rack_input.respond_to?(:set_encoding)
64
-
65
- env.update({"rack.version" => Rack::VERSION,
66
- "rack.input" => rack_input,
67
- "rack.errors" => $stderr,
68
-
69
- "rack.multithread" => true,
70
- "rack.multiprocess" => false,
71
- "rack.run_once" => false,
72
-
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,
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["SCRIPT_NAME"].length
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["REQUEST_PATH"] ||= [env["SCRIPT_NAME"], env[PATH_INFO]].join
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
- next if k.downcase == "rack.hijack"
93
-
94
- if k.downcase == "set-cookie"
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
- klass.split("::").inject(Object) { |o, x| o.const_get(x) }
22
+ const_get(klass)
21
23
  else
22
- _const_get(server, false)
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
- def self.default(options = {})
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 ['thin', 'puma', 'webrick']
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
- require 'rack/body_proxy'
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
- def initialize(app)
9
- @app = app
10
- end
6
+ class Head
7
+ def initialize(app)
8
+ @app = app
9
+ end
11
10
 
12
- def call(env)
13
- status, headers, body = @app.call(env)
11
+ def call(env)
12
+ status, headers, body = @app.call(env)
14
13
 
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
- ]
21
- else
22
- [status, headers, body]
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