summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-06-29 18:01:41 -0700
committerEric Wong <normalperson@yhbt.net>2009-06-29 18:17:36 -0700
commit41f6f65a6cb7152b5181704373d7da62704a62e8 (patch)
tree7ca9dd0d8618e11e42ca591b96d8b4f1d3f7942a
parent4f05fb1a3b44f8eab1a9dda26d5b115f33a149cd (diff)
This won't be heavily used enough to make preallocation worth
the effort.  While we're at it, don't enforce policy by forcing
the readpartial buffer to be Encoding::BINARY (even though it
/should/ be :), it's up to the user of the interface to decide.
-rw-r--r--lib/unicorn/chunked_reader.rb13
-rw-r--r--lib/unicorn/http_request.rb3
-rw-r--r--test/unit/test_chunked_reader.rb64
3 files changed, 38 insertions, 42 deletions
diff --git a/lib/unicorn/chunked_reader.rb b/lib/unicorn/chunked_reader.rb
index 41193d0..40d421d 100644
--- a/lib/unicorn/chunked_reader.rb
+++ b/lib/unicorn/chunked_reader.rb
@@ -6,22 +6,13 @@ module Unicorn; end
 module Unicorn
   class ChunkedReader
 
-    def initialize
-      @input = @buf = nil
-      @chunk_left = 0
-    end
-
-    def reopen(input, buf)
-      buf ||= Z.dup
-      buf.force_encoding(Encoding::BINARY) if buf.respond_to?(:force_encoding)
+    def initialize(input, buf)
       @input, @buf = input, buf
+      @chunk_left = 0
       parse_chunk_header
-      self
     end
 
     def readpartial(max, buf = Z.dup)
-      buf.force_encoding(Encoding::BINARY) if buf.respond_to?(:force_encoding)
-
       while @input && @chunk_left <= 0 && ! parse_chunk_header
         @buf << @input.readpartial(Const::CHUNK_SIZE, buf)
       end
diff --git a/lib/unicorn/http_request.rb b/lib/unicorn/http_request.rb
index b1cd8ed..b2c72f3 100644
--- a/lib/unicorn/http_request.rb
+++ b/lib/unicorn/http_request.rb
@@ -22,7 +22,6 @@ module Unicorn
     }
 
     NULL_IO = StringIO.new(Z)
-    DECHUNKER = ChunkedReader.new
     LOCALHOST = '127.0.0.1'.freeze
 
     # Being explicitly single-threaded, we have certain advantages in
@@ -93,7 +92,7 @@ module Unicorn
 
         if te = PARAMS[Const::HTTP_TRANSFER_ENCODING]
           if /chunked/i =~ te
-            socket = DECHUNKER.reopen(socket, body)
+            socket = ChunkedReader.new(socket, body)
             length = body = nil
           end
         end
diff --git a/test/unit/test_chunked_reader.rb b/test/unit/test_chunked_reader.rb
index d9fc56f..ec5c68a 100644
--- a/test/unit/test_chunked_reader.rb
+++ b/test/unit/test_chunked_reader.rb
@@ -7,7 +7,6 @@ require 'digest/sha1'
 class TestChunkedReader < Test::Unit::TestCase
 
   def setup
-    @cr = Unicorn::ChunkedReader.new
     @rd, @wr = IO.pipe
     @rd.binmode
     @wr.binmode
@@ -22,32 +21,32 @@ class TestChunkedReader < Test::Unit::TestCase
   end
 
   def test_eof1
-    @cr.reopen(@rd, "0\r\n")
-    assert_raises(EOFError) { @cr.readpartial(8192) }
+    cr = bin_reader(@rd, "0\r\n")
+    assert_raises(EOFError) { cr.readpartial(8192) }
   end
 
   def test_eof2
-    @cr.reopen(@rd, "0\r\n\r\n")
-    assert_raises(EOFError) { @cr.readpartial(8192) }
+    cr = bin_reader(@rd, "0\r\n\r\n")
+    assert_raises(EOFError) { cr.readpartial(8192) }
   end
 
   def test_readpartial1
-    @cr.reopen(@rd, "4\r\nasdf\r\n0\r\n")
-    assert_equal 'asdf', @cr.readpartial(8192)
-    assert_raises(EOFError) { @cr.readpartial(8192) }
+    cr = bin_reader(@rd, "4\r\nasdf\r\n0\r\n")
+    assert_equal 'asdf', cr.readpartial(8192)
+    assert_raises(EOFError) { cr.readpartial(8192) }
   end
 
   def test_gets1
-    @cr.reopen(@rd, "4\r\nasdf\r\n0\r\n")
+    cr = bin_reader(@rd, "4\r\nasdf\r\n0\r\n")
     STDOUT.sync = true
-    assert_equal 'asdf', @cr.gets
-    assert_raises(EOFError) { @cr.readpartial(8192) }
+    assert_equal 'asdf', cr.gets
+    assert_raises(EOFError) { cr.readpartial(8192) }
   end
 
   def test_gets2
-    @cr.reopen(@rd, "4\r\nasd\n\r\n0\r\n\r\n")
-    assert_equal "asd\n", @cr.gets
-    assert_nil @cr.gets
+    cr = bin_reader(@rd, "4\r\nasd\n\r\n0\r\n\r\n")
+    assert_equal "asd\n", cr.gets
+    assert_nil cr.gets
   end
 
   def test_gets3
@@ -55,12 +54,12 @@ class TestChunkedReader < Test::Unit::TestCase
     str = ('a' * max).freeze
     first = 5
     last = str.size - first
-    @cr.reopen(@rd,
+    cr = bin_reader(@rd,
       "#{'%x' % first}\r\n#{str[0, first]}\r\n" \
       "#{'%x' % last}\r\n#{str[-last, last]}\r\n" \
       "0\r\n")
-    assert_equal str, @cr.gets
-    assert_nil @cr.gets
+    assert_equal str, cr.gets
+    assert_nil cr.gets
   end
 
   def test_readpartial_gets_mixed1
@@ -68,17 +67,17 @@ class TestChunkedReader < Test::Unit::TestCase
     str = ('a' * max).freeze
     first = 5
     last = str.size - first
-    @cr.reopen(@rd,
+    cr = bin_reader(@rd,
       "#{'%x' % first}\r\n#{str[0, first]}\r\n" \
       "#{'%x' % last}\r\n#{str[-last, last]}\r\n" \
       "0\r\n")
-    partial = @cr.readpartial(16384)
+    partial = cr.readpartial(16384)
     assert String === partial
 
     len = max - partial.size
-    assert_equal(str[-len, len], @cr.gets)
-    assert_raises(EOFError) { @cr.readpartial(1) }
-    assert_nil @cr.gets
+    assert_equal(str[-len, len], cr.gets)
+    assert_raises(EOFError) { cr.readpartial(1) }
+    assert_nil cr.gets
   end
 
   def test_gets_mixed_readpartial
@@ -86,16 +85,16 @@ class TestChunkedReader < Test::Unit::TestCase
     str = ("z\n" * max).freeze
     first = 5
     last = str.size - first
-    @cr.reopen(@rd,
+    cr = bin_reader(@rd,
       "#{'%x' % first}\r\n#{str[0, first]}\r\n" \
       "#{'%x' % last}\r\n#{str[-last, last]}\r\n" \
       "0\r\n")
-    assert_equal("z\n", @cr.gets)
-    assert_equal("z\n", @cr.gets)
+    assert_equal("z\n", cr.gets)
+    assert_equal("z\n", cr.gets)
   end
 
   def test_dd
-    @cr.reopen(@rd, "6\r\nhello\n\r\n")
+    cr = bin_reader(@rd, "6\r\nhello\n\r\n")
     tmp = Tempfile.new('test_dd')
     tmp.sync = true
 
@@ -122,11 +121,11 @@ class TestChunkedReader < Test::Unit::TestCase
         exit 0
       end while true
     }
-    assert_equal "hello\n", @cr.gets
+    assert_equal "hello\n", cr.gets
     sha1 = Digest::SHA1.new
-    buf = ''
+    buf = Unicorn::Z.dup
     begin
-      @cr.readpartial(16384, buf)
+      cr.readpartial(16384, buf)
       sha1.update(buf)
     rescue EOFError
       break
@@ -142,4 +141,11 @@ class TestChunkedReader < Test::Unit::TestCase
     assert_equal sha1_file.hexdigest, sha1.hexdigest
   end
 
+private
+
+  def bin_reader(sock, buf)
+    buf.force_encoding(Encoding::BINARY) if buf.respond_to?(:force_encoding)
+    Unicorn::ChunkedReader.new(sock, buf)
+  end
+
 end