about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorwhy <why@19e92222-5c0b-0410-8929-a290d50e31e9>2006-04-11 01:46:13 +0000
committerwhy <why@19e92222-5c0b-0410-8929-a290d50e31e9>2006-04-11 01:46:13 +0000
commitc8e46fcb007a8599cac1b3861744669b1eab9406 (patch)
tree6f882e46503809faa25287456bbea83123e17c6b
parent3e5ca782bccb6676c2950b0e84cc3eefec5e8ca1 (diff)
downloadunicorn-c8e46fcb007a8599cac1b3861744669b1eab9406.tar.gz
git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@157 19e92222-5c0b-0410-8929-a290d50e31e9
-rwxr-xr-xexamples/camping/blog.rb2
-rw-r--r--lib/mongrel.rb28
-rw-r--r--lib/mongrel/camping.rb3
-rw-r--r--lib/mongrel/cgi.rb2
4 files changed, 25 insertions, 10 deletions
diff --git a/examples/camping/blog.rb b/examples/camping/blog.rb
index 18732a4..81a87da 100755
--- a/examples/camping/blog.rb
+++ b/examples/camping/blog.rb
@@ -281,7 +281,7 @@ if __FILE__ == $0
   # Use the Configurator as an example rather than Mongrel::Camping.start
   config = Mongrel::Configurator.new :host => "0.0.0.0" do
     listener :port => 3002 do
-      uri "/blog", :handler => CampingHandler.new(Blog)
+      uri "/blog", :handler => Mongrel::Camping::CampingHandler.new(Blog)
       uri "/favicon", :handler => Mongrel::Error404Handler.new("")
       trap("INT") { stop }
       run
diff --git a/lib/mongrel.rb b/lib/mongrel.rb
index 228fd9f..0a069fb 100644
--- a/lib/mongrel.rb
+++ b/lib/mongrel.rb
@@ -1,5 +1,6 @@
 require 'socket'
 require 'http11'
+require 'tempfile'
 require 'thread'
 require 'stringio'
 require 'mongrel/cgi'
@@ -125,6 +126,9 @@ module Mongrel
     # this, but we'd also like to do this as well.
     MAX_HEADER=1024 * (80 + 32)
 
+    # Maximum request body size before it is moved out of memory and into a tempfile for reading.
+    MAX_BODY=MAX_HEADER
+
     # A frozen format for this is about 15% faster
     STATUS_FORMAT = "HTTP/1.1 %d %s\r\nContent-Length: %d\r\nConnection: close\r\n".freeze
     CONTENT_TYPE = "Content-Type".freeze
@@ -164,13 +168,26 @@ module Mongrel
       @params = params
       @socket = socket
 
-      # now, if the initial_body isn't long enough for the content length we have to fill it
-      # TODO: adapt for big ass stuff by writing to a temp file
+      # if the body size is too large, move into a tempfile
       clen = params[Const::CONTENT_LENGTH].to_i
-      if @body.length < clen
-        @body << @socket.read(clen - @body.length)
+      if clen > Const::MAX_BODY
+        tmpf = Tempfile.new(self.class.name)
+        tmpf.binmode
+        tmpf.write(@body)
+        # TODO: throw an error if content-length doesn't match??
+        while clen > 0
+          readlen = clen < Const::CHUNK_SIZE ? clen : Const::CHUNK_SIZE
+          tmpf.write(@socket.read(readlen))
+          clen -= readlen
+        end
+        tmpf.rewind
+        @body = tmpf
+      else
+        if @body.length < clen
+          @body << @socket.read(clen - @body.length)
+        end
+        @body = StringIO.new(@body)
       end
-
     end
 
     def self.escape(s)
@@ -205,7 +222,6 @@ module Mongrel
       return params
     end
 
-    
   end
 
 
diff --git a/lib/mongrel/camping.rb b/lib/mongrel/camping.rb
index 5e42c9f..e305a9b 100644
--- a/lib/mongrel/camping.rb
+++ b/lib/mongrel/camping.rb
@@ -32,8 +32,7 @@ module Mongrel
       end
 
       def process(request, response)
-        req = StringIO.new(request.body)
-        controller = @klass.run(req, request.params)
+        controller = @klass.run(request.body, request.params)
         sendfile, clength = nil
         response.status = controller.status
         controller.headers.each do |k, v|
diff --git a/lib/mongrel/cgi.rb b/lib/mongrel/cgi.rb
index 14982e0..7e93ba3 100644
--- a/lib/mongrel/cgi.rb
+++ b/lib/mongrel/cgi.rb
@@ -35,7 +35,7 @@ module Mongrel
       @request = request
       @response = response
       @args = *args
-      @input = StringIO.new(request.body)
+      @input = request.body
       @head = {}
       @out_called = false
       super(*args)