about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-04-23 18:35:26 -0700
committerEric Wong <normalperson@yhbt.net>2009-04-23 18:35:26 -0700
commitd9c97a2e04e0455e2d2aa3e5ec6439c3b97a1b7c (patch)
tree247f773e33b151d1252a33d37cbb24276a0f4634
parentcfece4194f18aa2f93d372a6030f15990f5fe891 (diff)
downloadunicorn-d9c97a2e04e0455e2d2aa3e5ec6439c3b97a1b7c.tar.gz
StringIO.new(partial_body) does not update the offset for new
writes.  So instead create the StringIO object and then syswrite
to it and try to follow the same code path used by large uploads
which use Tempfiles.
-rw-r--r--lib/unicorn/http_request.rb13
-rw-r--r--test/unit/test_upload.rb23
2 files changed, 27 insertions, 9 deletions
diff --git a/lib/unicorn/http_request.rb b/lib/unicorn/http_request.rb
index 9be3b11..0de496f 100644
--- a/lib/unicorn/http_request.rb
+++ b/lib/unicorn/http_request.rb
@@ -96,15 +96,10 @@ module Unicorn
       remain = content_length - http_body.length
 
       # must read more data to complete body
-      if remain < Const::MAX_BODY
-        # small body, just use that
-        @body = StringIO.new(http_body)
-      else # huge body, put it in a tempfile
-        @body = Tempfile.new(Const::UNICORN_TMP_BASE)
-        @body.binmode
-        @body.sync = true
-        @body.syswrite(http_body)
-      end
+      @body = remain < Const::MAX_BODY ? StringIO.new : Tempfile.new('')
+      @body.binmode
+      @body.sync = true
+      @body.syswrite(http_body)
 
       # Some clients (like FF1.0) report 0 for body and then send a body.
       # This will probably truncate them but at least the request goes through
diff --git a/test/unit/test_upload.rb b/test/unit/test_upload.rb
index c4d6f6f..b06dfdb 100644
--- a/test/unit/test_upload.rb
+++ b/test/unit/test_upload.rb
@@ -51,6 +51,29 @@ class UploadTest < Test::Unit::TestCase
     assert_equal @sha1.hexdigest, resp[:sha1]
   end
 
+  def test_put_trickle_small
+    @count, @bs = 2, 128
+    start_server(@sha1_app)
+    assert_equal 256, length
+    sock = TCPSocket.new(@addr, @port)
+    hdr = "PUT / HTTP/1.0\r\nContent-Length: #{length}\r\n\r\n"
+    @count.times do
+      buf = @random.sysread(@bs)
+      @sha1.update(buf)
+      hdr << buf
+      sock.syswrite(hdr)
+      hdr = ''
+      sleep 0.6
+    end
+    read = sock.read.split(/\r\n/)
+    assert_equal "HTTP/1.1 200 OK", read[0]
+    resp = eval(read.grep(/^X-Resp: /).first.sub!(/X-Resp: /, ''))
+    assert_equal length, resp[:size]
+    assert_equal 0, resp[:pos]
+    assert_equal @sha1.hexdigest, resp[:sha1]
+    assert_equal StringIO, resp[:class]
+  end
+
   def test_tempfile_unlinked
     spew_path = lambda do |env|
       if orig = env['HTTP_X_OLD_PATH']