From d848cc43ddcd949eec85da93a636aef32541619c Mon Sep 17 00:00:00 2001
From: Ryan Tomayko <rtomayko@gmail.com>
Date: Thu, 5 Mar 2009 21:20:58 -0800
Subject: [PATCH 3/4] Rack::Lint no longer requires a Content-Length response header

---
 lib/rack/lint.rb       |   54 ++++++++++++++++-------------------------------
 test/spec_rack_lint.rb |   14 ------------
 2 files changed, 19 insertions(+), 49 deletions(-)

diff --git a/lib/rack/lint.rb b/lib/rack/lint.rb
index e549a9e..e77ee55 100644
--- a/lib/rack/lint.rb
+++ b/lib/rack/lint.rb
@@ -372,59 +372,43 @@ module Rack
 
     ## === The Content-Length
     def check_content_length(status, headers, env)
-      chunked_response = false
-      headers.each { |key, value|
-        if key.downcase == 'transfer-encoding'
-          chunked_response = value.downcase != 'identity'
-        end
-      }
-
       headers.each { |key, value|
         if key.downcase == 'content-length'
-          ## There must be a <tt>Content-Length</tt>, except when the
-          ## +Status+ is 1xx, 204 or 304, in which case there must be none
-          ## given.
+          ## There must not be a <tt>Content-Length</tt> header when the
+          ## +Status+ is 1xx, 204 or 304.
           assert("Content-Length header found in #{status} response, not allowed") {
             not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
           }
 
-          assert('Content-Length header should not be used if body is chunked') {
-            not chunked_response
-          }
-
           bytes = 0
           string_body = true
 
-          @body.each { |part|
-            unless part.kind_of?(String)
-              string_body = false
-              break
-            end
+          if @body.respond_to?(:to_ary)
+            @body.each { |part|
+              unless part.kind_of?(String)
+                string_body = false
+                break
+              end
 
-            bytes += Rack::Utils.bytesize(part)
-          }
-
-          if env["REQUEST_METHOD"] == "HEAD"
-            assert("Response body was given for HEAD request, but should be empty") {
-              bytes == 0
+              bytes += Rack::Utils.bytesize(part)
             }
-          else
-            if string_body
-              assert("Content-Length header was #{value}, but should be #{bytes}") {
-                value == bytes.to_s
+
+            if env["REQUEST_METHOD"] == "HEAD"
+              assert("Response body was given for HEAD request, but should be empty") {
+                bytes == 0
               }
+            else
+              if string_body
+                assert("Content-Length header was #{value}, but should be #{bytes}") {
+                  value == bytes.to_s
+                }
+              end
             end
           end
 
           return
         end
       }
-
-      if [ String, Array ].include?(@body.class) && !chunked_response
-        assert('No Content-Length header found') {
-          Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
-        }
-      end
     end
 
     ## === The Body
diff --git a/test/spec_rack_lint.rb b/test/spec_rack_lint.rb
index 2e78748..0b4d6fb 100644
--- a/test/spec_rack_lint.rb
+++ b/test/spec_rack_lint.rb
@@ -222,13 +222,6 @@ context "Rack::Lint" do
   end
 
   specify "notices content-length errors" do
-    lambda {
-      Rack::Lint.new(lambda { |env|
-                       [200, {"Content-type" => "text/plain"}, []]
-                     }).call(env({}))
-    }.should.raise(Rack::Lint::LintError).
-      message.should.match(/No Content-Length/)
-
     [100, 101, 204, 304].each do |status|
       lambda {
         Rack::Lint.new(lambda { |env|
@@ -240,13 +233,6 @@ context "Rack::Lint" do
 
     lambda {
       Rack::Lint.new(lambda { |env|
-                       [200, {"Content-type" => "text/plain", "Content-Length" => "0", "Transfer-Encoding" => "chunked"}, []]
-                     }).call(env({}))
-    }.should.raise(Rack::Lint::LintError).
-      message.should.match(/Content-Length header should not be used/)
-
-    lambda {
-      Rack::Lint.new(lambda { |env|
                        [200, {"Content-type" => "text/plain", "Content-Length" => "1"}, []]
                      }).call(env({}))
     }.should.raise(Rack::Lint::LintError).
-- 
1.6.2

