From 41f6f65a6cb7152b5181704373d7da62704a62e8 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 29 Jun 2009 18:01:41 -0700 Subject: chunked_reader: simpler interface 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. --- lib/unicorn/chunked_reader.rb | 13 ++------ lib/unicorn/http_request.rb | 3 +- test/unit/test_chunked_reader.rb | 64 ++++++++++++++++++++++------------------ 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 -- cgit v1.2.3-24-ge0c7