summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-10-07 06:55:22 +0000
committerEric Wong <normalperson@yhbt.net>2010-10-07 06:55:22 +0000
commit8daf254356241c135ad2c843de567910528a10a7 (patch)
tree4202db8e7c4c53204f3a0b96d4edf37625e7ea5e
parent090f56bb79a8ec734719d9be90daa3cd01d29871 (diff)
This should be easier for Rainbows! to use
-rw-r--r--lib/unicorn.rb2
-rw-r--r--lib/unicorn/http_request.rb37
-rw-r--r--lib/unicorn/http_server.rb2
-rw-r--r--lib/unicorn/tee_input.rb104
-rw-r--r--test/unit/test_tee_input.rb9
5 files changed, 72 insertions, 82 deletions
diff --git a/lib/unicorn.rb b/lib/unicorn.rb
index f9d5954..622dc6c 100644
--- a/lib/unicorn.rb
+++ b/lib/unicorn.rb
@@ -73,11 +73,11 @@ class Unicorn::ClientShutdown < EOFError; end
 
 require 'unicorn/const'
 require 'unicorn/socket_helper'
+require 'unicorn/tee_input'
 require 'unicorn/http_request'
 require 'unicorn/configurator'
 require 'unicorn/tmpio'
 require 'unicorn/util'
-require 'unicorn/tee_input'
 require 'unicorn/http_response'
 require 'unicorn/worker'
 require 'unicorn/http_server'
diff --git a/lib/unicorn/http_request.rb b/lib/unicorn/http_request.rb
index 13e9900..2dcd839 100644
--- a/lib/unicorn/http_request.rb
+++ b/lib/unicorn/http_request.rb
@@ -2,7 +2,9 @@
 
 require 'unicorn_http'
 
-class Unicorn::HttpRequest
+# TODO: remove redundant names
+Unicorn.const_set(:HttpRequest, Unicorn::HttpParser)
+class Unicorn::HttpParser
 
   # default parameters we merge into the request env for Rack handlers
   DEFAULTS = {
@@ -23,20 +25,9 @@ class Unicorn::HttpRequest
   # A frozen format for this is about 15% faster
   REMOTE_ADDR = 'REMOTE_ADDR'.freeze
   RACK_INPUT = 'rack.input'.freeze
+  TeeInput = Unicorn::TeeInput
   # :startdoc:
 
-  attr_reader :env, :parser, :buf
-
-  def initialize
-    @parser = Unicorn::HttpParser.new
-    @buf = ""
-    @env = {}
-  end
-
-  def response_headers?
-    @parser.headers?
-  end
-
   # Does the majority of the IO processing.  It has been written in
   # Ruby using about 8 different IO processing strategies.
   #
@@ -51,8 +42,8 @@ class Unicorn::HttpRequest
   # This does minimal exception trapping and it is up to the caller
   # to handle any socket errors (e.g. user aborted upload).
   def read(socket)
-    @env.clear
-    @parser.reset
+    reset
+    e = env
 
     # From http://www.ietf.org/rfc/rfc3875:
     # "Script authors should be aware that the REMOTE_ADDR and
@@ -61,18 +52,18 @@ class Unicorn::HttpRequest
     #  identify the client for the immediate request to the server;
     #  that client may be a proxy, gateway, or other intermediary
     #  acting on behalf of the actual source client."
-    @env[REMOTE_ADDR] = socket.kgio_addr
+    e[REMOTE_ADDR] = socket.kgio_addr
 
     # short circuit the common case with small GET requests first
-    if @parser.headers(@env, socket.kgio_read!(16384, @buf)).nil?
+    socket.kgio_read!(16384, buf)
+    if parse.nil?
       # Parser is not done, queue up more data to read and continue parsing
-      # an Exception thrown from the PARSER will throw us out of the loop
+      # an Exception thrown from the parser will throw us out of the loop
       begin
-        @buf << socket.kgio_read!(16384)
-      end while @parser.headers(@env, @buf).nil?
+        buf << socket.kgio_read!(16384)
+      end while parse.nil?
     end
-    @env[RACK_INPUT] = 0 == @parser.content_length ?
-                       NULL_IO : Unicorn::TeeInput.new(socket, self)
-    @env.merge!(DEFAULTS)
+    e[RACK_INPUT] = 0 == content_length ? NULL_IO : TeeInput.new(socket, self)
+    e.merge!(DEFAULTS)
   end
 end
diff --git a/lib/unicorn/http_server.rb b/lib/unicorn/http_server.rb
index 5d6c023..513269f 100644
--- a/lib/unicorn/http_server.rb
+++ b/lib/unicorn/http_server.rb
@@ -521,7 +521,7 @@ class Unicorn::HttpServer
       r = @app.call(env)
     end
     # r may be frozen or const, so don't modify it
-    @request.response_headers? or r = [ r[0], nil, r[2] ]
+    @request.headers? or r = [ r[0], nil, r[2] ]
     http_response_write(client, r)
   rescue => e
     handle_error(client, e)
diff --git a/lib/unicorn/tee_input.rb b/lib/unicorn/tee_input.rb
index 32ee4f2..a3e01d2 100644
--- a/lib/unicorn/tee_input.rb
+++ b/lib/unicorn/tee_input.rb
@@ -11,8 +11,8 @@
 #
 # When processing uploads, Unicorn exposes a TeeInput object under
 # "rack.input" of the Rack environment.
-class Unicorn::TeeInput < Struct.new(:socket, :req, :parser,
-                                     :buf, :len, :tmp, :buf2)
+class Unicorn::TeeInput
+  attr_accessor :tmp, :socket, :parser, :env, :buf, :len, :buf2
 
   # The maximum size (in +bytes+) to buffer in memory before
   # resorting to a temporary file.  Default is 112 kilobytes.
@@ -26,18 +26,18 @@ class Unicorn::TeeInput < Struct.new(:socket, :req, :parser,
   # Initializes a new TeeInput object.  You normally do not have to call
   # this unless you are writing an HTTP server.
   def initialize(socket, request)
-    self.socket = socket
-    self.req = request.env
-    self.parser = request.parser
-    self.buf = request.buf
-    self.len = parser.content_length
-    self.tmp = len && len < @@client_body_buffer_size ?
-               StringIO.new("") : Unicorn::TmpIO.new
-    self.buf2 = ""
-    if buf.size > 0
-      parser.filter_body(buf2, buf) and finalize_input
-      tmp.write(buf2)
-      tmp.rewind
+    @socket = socket
+    @parser = request
+    @buf = request.buf
+    @env = request.env
+    @len = request.content_length
+    @tmp = @len && @len < @@client_body_buffer_size ?
+           StringIO.new("") : Unicorn::TmpIO.new
+    @buf2 = ""
+    if @buf.size > 0
+      @parser.filter_body(@buf2, @buf) and finalize_input
+      @tmp.write(@buf2)
+      @tmp.rewind
     end
   end
 
@@ -58,16 +58,16 @@ class Unicorn::TeeInput < Struct.new(:socket, :req, :parser,
   # earlier.  Most applications should only need to call +read+ with a
   # specified +length+ in a loop until it returns +nil+.
   def size
-    len and return len
+    @len and return @len
 
     if socket
-      pos = tmp.pos
-      while tee(@@io_chunk_size, buf2)
+      pos = @tmp.pos
+      while tee(@@io_chunk_size, @buf2)
       end
-      tmp.seek(pos)
+      @tmp.seek(pos)
     end
 
-    self.len = tmp.size
+    @len = @tmp.size
   end
 
   # :call-seq:
@@ -90,22 +90,22 @@ class Unicorn::TeeInput < Struct.new(:socket, :req, :parser,
   # any data and only block when nothing is available (providing
   # IO#readpartial semantics).
   def read(*args)
-    socket or return tmp.read(*args)
+    @socket or return @tmp.read(*args)
 
     length = args.shift
     if nil == length
-      rv = tmp.read || ""
-      while tee(@@io_chunk_size, buf2)
-        rv << buf2
+      rv = @tmp.read || ""
+      while tee(@@io_chunk_size, @buf2)
+        rv << @buf2
       end
       rv
     else
       rv = args.shift || ""
-      diff = tmp.size - tmp.pos
+      diff = @tmp.size - @tmp.pos
       if 0 == diff
         ensure_length(tee(length, rv), length)
       else
-        ensure_length(tmp.read(diff > length ? length : diff, rv), length)
+        ensure_length(@tmp.read(diff > length ? length : diff, rv), length)
       end
     end
   end
@@ -120,27 +120,27 @@ class Unicorn::TeeInput < Struct.new(:socket, :req, :parser,
   # This takes zero arguments for strict Rack::Lint compatibility,
   # unlike IO#gets.
   def gets
-    socket or return tmp.gets
+    @socket or return @tmp.gets
     sep = $/ or return read
 
-    orig_size = tmp.size
-    if tmp.pos == orig_size
-      tee(@@io_chunk_size, buf2) or return nil
-      tmp.seek(orig_size)
+    orig_size = @tmp.size
+    if @tmp.pos == orig_size
+      tee(@@io_chunk_size, @buf2) or return nil
+      @tmp.seek(orig_size)
     end
 
     sep_size = Rack::Utils.bytesize(sep)
-    line = tmp.gets # cannot be nil here since size > pos
+    line = @tmp.gets # cannot be nil here since size > pos
     sep == line[-sep_size, sep_size] and return line
 
-    # unlikely, if we got here, then tmp is at EOF
+    # unlikely, if we got here, then @tmp is at EOF
     begin
-      orig_size = tmp.pos
-      tee(@@io_chunk_size, buf2) or break
-      tmp.seek(orig_size)
-      line << tmp.gets
+      orig_size = @tmp.pos
+      tee(@@io_chunk_size, @buf2) or break
+      @tmp.seek(orig_size)
+      line << @tmp.gets
       sep == line[-sep_size, sep_size] and return line
-      # tmp is at EOF again here, retry the loop
+      # @tmp is at EOF again here, retry the loop
     end while true
 
     line
@@ -166,7 +166,7 @@ class Unicorn::TeeInput < Struct.new(:socket, :req, :parser,
   # the offset (zero) of the +ios+ pointer.  Subsequent reads will
   # start from the beginning of the previously-buffered input.
   def rewind
-    tmp.rewind # Rack does not specify what the return value is here
+    @tmp.rewind # Rack does not specify what the return value is here
   end
 
 private
@@ -175,11 +175,11 @@ private
   # backing store as well as returning it.  +dst+ must be specified.
   # returns nil if reading from the input returns nil
   def tee(length, dst)
-    unless parser.body_eof?
-      r = socket.kgio_read(length, buf) or eof!
-      unless parser.filter_body(dst, r)
-        tmp.write(dst)
-        tmp.seek(0, IO::SEEK_END) # workaround FreeBSD/OSX + MRI 1.8.x bug
+    unless @parser.body_eof?
+      r = @socket.kgio_read(length, @buf) or eof!
+      unless @parser.filter_body(dst, @buf)
+        @tmp.write(dst)
+        @tmp.seek(0, IO::SEEK_END) # workaround FreeBSD/OSX + MRI 1.8.x bug
         return dst
       end
     end
@@ -187,11 +187,11 @@ private
   end
 
   def finalize_input
-    while parser.trailers(req, buf).nil?
-      r = socket.kgio_read(@@io_chunk_size) or eof!
-      buf << r
+    while @parser.trailers(@env, @buf).nil?
+      r = @socket.kgio_read(@@io_chunk_size) or eof!
+      @buf << r
     end
-    self.socket = nil
+    @socket = nil
   end
 
   # tee()s into +dst+ until it is of +length+ bytes (or until
@@ -204,10 +204,10 @@ private
     # len is nil for chunked bodies, so we can't ensure length for those
     # since they could be streaming bidirectionally and we don't want to
     # block the caller in that case.
-    return dst if dst.nil? || len.nil?
+    return dst if dst.nil? || @len.nil?
 
-    while dst.size < length && tee(length - dst.size, buf2)
-      dst << buf2
+    while dst.size < length && tee(length - dst.size, @buf2)
+      dst << @buf2
     end
 
     dst
@@ -218,7 +218,7 @@ private
     # we do support clients that shutdown(SHUT_WR) after the
     # _entire_ request has been sent, and those will not have
     # raised EOFError on us.
-    socket.close if socket
-    raise Unicorn::ClientShutdown, "bytes_read=#{tmp.size}", []
+    @socket.close if @socket
+    raise Unicorn::ClientShutdown, "bytes_read=#{@tmp.size}", []
   end
 end
diff --git a/test/unit/test_tee_input.rb b/test/unit/test_tee_input.rb
index 263aa8a..a10ca34 100644
--- a/test/unit/test_tee_input.rb
+++ b/test/unit/test_tee_input.rb
@@ -5,7 +5,6 @@ require 'digest/sha1'
 require 'unicorn'
 
 class TestTeeInput < Test::Unit::TestCase
-  MockRequest = Struct.new(:env, :parser, :buf)
 
   def setup
     @rs = $/
@@ -164,7 +163,7 @@ class TestTeeInput < Test::Unit::TestCase
       @wr.write("0\r\n\r\n")
     }
     @wr.close
-    ti = Unicorn::TeeInput.new(@rd, MockRequest.new(@env, @parser, @buf))
+    ti = Unicorn::TeeInput.new(@rd, @parser)
     assert_nil @parser.content_length
     assert_nil ti.len
     assert ! @parser.body_eof?
@@ -202,7 +201,7 @@ class TestTeeInput < Test::Unit::TestCase
       end
       @wr.write("0\r\n\r\n")
     }
-    ti = Unicorn::TeeInput.new(@rd, MockRequest.new(@env, @parser, @buf))
+    ti = Unicorn::TeeInput.new(@rd, @parser)
     assert_nil @parser.content_length
     assert_nil ti.len
     assert ! @parser.body_eof?
@@ -231,7 +230,7 @@ class TestTeeInput < Test::Unit::TestCase
       @wr.write("Hello: World\r\n\r\n")
     }
     @wr.close
-    ti = Unicorn::TeeInput.new(@rd, MockRequest.new(@env, @parser, @buf))
+    ti = Unicorn::TeeInput.new(@rd, @parser)
     assert_nil @parser.content_length
     assert_nil ti.len
     assert ! @parser.body_eof?
@@ -253,7 +252,7 @@ private
            "\r\n#{body}"
     assert_equal @env, @parser.headers(@env, @buf)
     assert_equal body, @buf
-    MockRequest.new(@env, @parser, @buf)
+    @parser
   end
 
 end