about summary refs log tree commit homepage
path: root/lib/mongrel.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mongrel.rb')
-rw-r--r--lib/mongrel.rb66
1 files changed, 35 insertions, 31 deletions
diff --git a/lib/mongrel.rb b/lib/mongrel.rb
index a801148..cd2a860 100644
--- a/lib/mongrel.rb
+++ b/lib/mongrel.rb
@@ -135,7 +135,7 @@ module Mongrel
     ERROR_503_RESPONSE="HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY".freeze
 
     # The basic max request size we'll try to read.
-    CHUNK_SIZE=(4 * 1024)
+    CHUNK_SIZE=(16 * 1024)
 
     # This is the maximum header that is allowed before a client is booted.  The parser detects
     # this, but we'd also like to do this as well.
@@ -195,41 +195,44 @@ module Mongrel
       @params = params
       @socket = socket
       content_length = params[Const::CONTENT_LENGTH].to_i
-      http_body_len = params.http_body.length
+      remain = content_length - params.http_body.length
+      
 
       dispatcher.request_begins(params) if dispatcher
+      STDERR.puts "REQUEST: #{params.inspect}"
 
-      # conditions to test:
-      #   * http_body_len == 0 && content_length == 0  -- Nothing to do
-      #   * http_body_len > content_length -- ERROR, abort
-      #   * http_body_len < content_length -- need to read more
-      #   * http_body_len == content_length -- initial body has all of it
-      if http_body_len == 0 && content_length == 0
-        # no body to process
+      if remain == 0
+        # we've got everything, pack it up
+        STDERR.puts "everything already read, packing up and done: #{params.http_body.inspect}"
         @body = StringIO.new
-        dispatcher.request_progress(params, 0, 0) if dispatcher
-      elsif http_body_len > content_length
+        @body.write params.http_body
+        dispatcher.request_progress(params, 0, content_length) if dispatcher
+      elsif remain < 0
+        STDERR.puts "ERROR: body length larger than content length, stupid client"
         # ERROR, they're sending bad requests
-        raise HttpParserError.new("Sent body size #{http_body_len} but declared Content-Length: #{content_length}")
-      elsif http_body_len < content_length
+        raise HttpParserError.new("Sent body size #{params.http_body.length} but declared Content-Length: #{content_length}")
+      elsif remain > 0
+        STDERR.puts "need to read #{remain} more of the body #{content_length}"
         # must read more data to complete body
-        clen = content_length - http_body_len
-        if clen > Const::MAX_BODY
+        if remain > Const::MAX_BODY
+          STDERR.puts "Big content, saving to tempfile"
           # huge body, put it in a tempfile
           @body = Tempfile.new(Const::MONGREL_TMP_BASE)
           @body.binmode
         else
           # small body, just use that
-          @body = StringIO.new(params.http_body)
+          STDERR.puts "Small file, using ram"
+          @body = StringIO.new
         end
-        read_body(clen, dispatcher)
-      elsif http_body_len == content_length
-        # we've got everything, pack it up
-        @body = StringIO.new(params.http_body)
-        dispatcher.request_progress(params, 0, http_body_len) if dispatcher
+
+        @body.write params.http_body
+        read_body(remain, content_length, dispatcher)
       else
         STDERR.puts "BAD LOGIC: Tell Zed he's a moron."
       end
+
+      @body.rewind
+      STDERR.puts "DONE"
     end
 
 
@@ -237,26 +240,27 @@ module Mongrel
     # small chunks.  It expects @body to be an IO object, @socket to be valid,
     # and will set @body = nil if the request fails.  It also expects any initial
     # part of the body that has been read to be in the @body already.
-    def read_body(clen, dispatcher)
+    def read_body(remain, total, dispatcher)
+      STDERR.puts "reading body"
       begin
-        total = clen
         # write the odd sized chunk first
-        clen -= @body.write(@socket.read(clen % Const::CHUNK_SIZE))
-        dispatcher.request_progress(params, clen, total) if dispatcher
+        remain -= @body.write(@socket.read(remain % Const::CHUNK_SIZE))
+        STDERR.puts "first read, remaining: #{remain}"
+        dispatcher.request_progress(params, remain, total) if dispatcher
 
         # then stream out nothing but perfectly sized chunks
-        while clen > 0 and !@socket.closed?
+        until remain <= 0 or @socket.closed?
           data = @socket.read(Const::CHUNK_SIZE)
+          STDERR.puts "read #{data.length} more"
           # have to do it this way since @socket.eof? causes it to block
           raise "Socket closed or read failure" if not data or data.length != Const::CHUNK_SIZE
-          clen -= @body.write(data)
+          remain -= @body.write(data)
           # ASSUME: we are writing to a disk and these writes always write the requested amount
-          dispatcher.request_progress(params, clen, total) if dispatcher
+          dispatcher.request_progress(params, remain, total) if dispatcher
         end
-
-        # rewind to keep the world happy
-        @body.rewind
       rescue Object
+        STDERR.puts "ERROR reading http body: #$!"
+        $!.backtrace.join("\n")
         # any errors means we should delete the file, including if the file is dumped
         @socket.close unless @socket.closed?
         @body.delete if @body.class == Tempfile