summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-04-16 22:28:06 -0700
committerEric Wong <normalperson@yhbt.net>2009-04-16 22:31:32 -0700
commit95fa512342b4495cf9d56bbf663aa2114a85a4e1 (patch)
tree49f05085be19f91c2c63d11c5fddc31d9827030d
parent9c4c5f03b5dccbbaa263a0d0eace0fca3a2d1180 (diff)
Avoid creating new string objects and then discarding them right
away by stuffing non-constant but always-present headers into
the initial output.
-rw-r--r--lib/unicorn/http_response.rb11
-rw-r--r--test/unit/test_response.rb4
2 files changed, 8 insertions, 7 deletions
diff --git a/lib/unicorn/http_response.rb b/lib/unicorn/http_response.rb
index c0b1081..b355ad4 100644
--- a/lib/unicorn/http_response.rb
+++ b/lib/unicorn/http_response.rb
@@ -25,15 +25,13 @@ module Unicorn
     # Connection: and Date: headers no matter what (if anything) our
     # Rack application sent us.
     SKIP = { 'connection' => true, 'date' => true, 'status' => true }.freeze
+    HEADER_OUT = [ "Connection: close" ] # :nodoc
 
     # writes the rack_response to socket as an HTTP response
     def self.write(socket, rack_response)
       status, headers, body = rack_response
       status = "#{status} #{HTTP_STATUS_CODES[status]}"
-
-      # Date is required by HTTP/1.1 as long as our clock can be trusted.
-      # Some broken clients require a "Status" header so we accomodate them
-      out = [ "Date: #{Time.now.httpdate}", "Status: #{status}" ]
+      out = HEADER_OUT.dup # shallow copy
 
       # Don't bother enforcing duplicate supression, it's a Hash most of
       # the time anyways so just hope our app knows what it's doing
@@ -48,9 +46,12 @@ module Unicorn
 
       # Rack should enforce Content-Length or chunked transfer encoding,
       # so don't worry or care about them.
+      # Date is required by HTTP/1.1 as long as our clock can be trusted.
+      # Some broken clients require a "Status" header so we accomodate them
       socket_write(socket,
                    "HTTP/1.1 #{status}\r\n" \
-                   "Connection: close\r\n" \
+                   "Date: #{Time.now.httpdate}\r\n" \
+                   "Status: #{status}\r\n" \
                    "#{out.join("\r\n")}\r\n\r\n")
       body.each { |chunk| socket_write(socket, chunk) }
       socket.close # uncorks the socket immediately
diff --git a/test/unit/test_response.rb b/test/unit/test_response.rb
index 8abc86c..1d47c57 100644
--- a/test/unit/test_response.rb
+++ b/test/unit/test_response.rb
@@ -60,7 +60,7 @@ class ResponseTest < Test::Unit::TestCase
     out = StringIO.new
     HttpResponse.write(out,[200, {"X-Whatever" => "stuff"}, []])
     assert out.closed?
-    assert_match(/^Status: 200 OK\r\nX-Whatever: stuff\r\n/, out.string)
+    assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/i).size
   end
 
   # we always favor the code returned by the application, since "Status"
@@ -71,7 +71,7 @@ class ResponseTest < Test::Unit::TestCase
     header_hash = {"X-Whatever" => "stuff", 'StaTus' => "666" }
     HttpResponse.write(out,[200, header_hash, []])
     assert out.closed?
-    assert_match(/^Status: 200 OK\r\nX-Whatever: stuff\r\n/, out.string)
+    assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/i).size
     assert_equal 1, out.string.split(/\r\n/).grep(/^Status:/i).size
   end