summary refs log tree commit
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-11-12 20:58:46 +0000
committerJames Tucker <jftucker@gmail.com>2014-07-14 21:11:13 -0700
commit895beec0622d3cafdc5fbae20d665c6d5f6c8e7c (patch)
tree8988dbe6235990f8549e46d8910e91e1412c6218
parentb51f3036fbdb911eac6b5cf97ebf9388fb1f14a9 (diff)
downloadrack-895beec0622d3cafdc5fbae20d665c6d5f6c8e7c.tar.gz
chunked: do not chunk on pre-HTTP/1.0 clients
Ancient HTTP clients which predate HTTP/1.0 may not set HTTP_VERSION
at all, and those do not support chunking.

RFC 1945 describes HTTP/0.9 as well as HTTP/1.0

Signed-off-by: James Tucker <jftucker@gmail.com>
-rw-r--r--lib/rack/chunked.rb13
-rw-r--r--test/spec_chunked.rb16
2 files changed, 28 insertions, 1 deletions
diff --git a/lib/rack/chunked.rb b/lib/rack/chunked.rb
index a400756a..ea221fa9 100644
--- a/lib/rack/chunked.rb
+++ b/lib/rack/chunked.rb
@@ -39,11 +39,22 @@ module Rack
       @app = app
     end
 
+    # pre-HTTP/1.0 (informally "HTTP/0.9") HTTP requests did not have
+    # a version (nor response headers)
+    def chunkable_version?(ver)
+      case ver
+      when "HTTP/1.0", nil, "HTTP/0.9"
+        false
+      else
+        true
+      end
+    end
+
     def call(env)
       status, headers, body = @app.call(env)
       headers = HeaderHash.new(headers)
 
-      if env['HTTP_VERSION'] == 'HTTP/1.0' ||
+      if ! chunkable_version?(env['HTTP_VERSION']) ||
          STATUS_WITH_NO_ENTITY_BODY.include?(status) ||
          headers['Content-Length'] ||
          headers['Transfer-Encoding']
diff --git a/test/spec_chunked.rb b/test/spec_chunked.rb
index 12f21581..0a6d9ff1 100644
--- a/test/spec_chunked.rb
+++ b/test/spec_chunked.rb
@@ -64,6 +64,22 @@ describe Rack::Chunked do
     body.join.should.equal 'Hello World!'
   end
 
+  should 'not modify response when client is ancient, pre-HTTP/1.0' do
+    app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
+    check = lambda do
+      status, headers, body = chunked(app).call(@env.dup)
+      status.should.equal 200
+      headers.should.not.include 'Transfer-Encoding'
+      body.join.should.equal 'Hello World!'
+    end
+
+    @env.delete('HTTP_VERSION') # unicorn will do this on pre-HTTP/1.0 requests
+    check.call
+
+    @env['HTTP_VERSION'] = 'HTTP/0.9' # not sure if this happens in practice
+    check.call
+  end
+
   should 'not modify response when Transfer-Encoding header already present' do
     app = lambda { |env|
       [200, {"Content-Type" => "text/plain", 'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']]