about summary refs log tree commit homepage
path: root/lib/unicorn/http_response.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/unicorn/http_response.rb')
-rw-r--r--lib/unicorn/http_response.rb23
1 files changed, 8 insertions, 15 deletions
diff --git a/lib/unicorn/http_response.rb b/lib/unicorn/http_response.rb
index 114243c..3d7cd50 100644
--- a/lib/unicorn/http_response.rb
+++ b/lib/unicorn/http_response.rb
@@ -5,20 +5,11 @@ module Unicorn
   # You use it by simply doing:
   #
   #   status, headers, body = rack_app.call(env)
-  #   HttpResponse.write(socket, [ status, headers, body ])
+  #   HttpResponse.write(socket, [ status, headers, body ], keepalive)
   #
   # Most header correctness (including Content-Length and Content-Type)
-  # is the job of Rack, with the exception of the "Connection: close"
+  # is the job of Rack, with the exception of the "Connection"
   # and "Date" headers.
-  #
-  # A design decision was made to force the client to not pipeline or
-  # keepalive requests.  HTTP/1.1 pipelining really kills the
-  # performance due to how it has to be handled and how unclear the
-  # standard is.  To fix this the HttpResponse always gives a
-  # "Connection: close" header which forces the client to close right
-  # away.  The bonus for this is that it gives a pretty nice speed boost
-  # to most clients since they can close their connection immediately.
-
   class HttpResponse
 
     # Every standard HTTP code mapped to the appropriate message.
@@ -27,16 +18,19 @@ module Unicorn
       hash
     }
 
+    CONN_CLOSE = "Connection: close\r\n"
+    CONN_ALIVE = "Connection: keep-alive\r\n"
+
     # Rack does not set/require a Date: header.  We always override the
     # Connection: and Date: headers no matter what (if anything) our
     # Rack application sent us.
     SKIP = { 'connection' => true, 'date' => true, 'status' => true }.freeze
 
     # writes the rack_response to socket as an HTTP response
-    def self.write(socket, rack_response)
+    def self.write(socket, rack_response, keepalive = false)
       status, headers, body = rack_response
       status = CODES[status.to_i] || status
-      tmp = []
+      tmp = [ keepalive ? CONN_ALIVE : CONN_CLOSE ]
 
       # 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
@@ -56,10 +50,9 @@ module Unicorn
       socket.write("HTTP/1.1 #{status}\r\n" \
                    "Date: #{Time.now.httpdate}\r\n" \
                    "Status: #{status}\r\n" \
-                   "Connection: close\r\n" \
                    "#{tmp.join(Z)}\r\n")
       body.each { |chunk| socket.write(chunk) }
-      socket.close # flushes and uncorks the socket immediately
+      keepalive or socket.close # flushes and uncorks the socket immediately
       ensure
         body.respond_to?(:close) and body.close rescue nil
     end