[Zope3-checkins] SVN: Zope3/trunk/ fixed http://zope.org/Collectors/Zope3-dev/714, ZServer sends now Connection headers correctly

Jodok Batlogg jodok.batlogg at lovelysystems.com
Sun Mar 11 06:45:30 EDT 2007


Log message for revision 73136:
  fixed http://zope.org/Collectors/Zope3-dev/714, ZServer sends now Connection headers correctly

Changed:
  U   Zope3/trunk/doc/CHANGES.txt
  U   Zope3/trunk/src/zope/server/http/httptask.py
  U   Zope3/trunk/src/zope/server/http/tests/test_httpserver.py

-=-
Modified: Zope3/trunk/doc/CHANGES.txt
===================================================================
--- Zope3/trunk/doc/CHANGES.txt	2007-03-10 12:34:07 UTC (rev 73135)
+++ Zope3/trunk/doc/CHANGES.txt	2007-03-11 10:45:28 UTC (rev 73136)
@@ -194,6 +194,9 @@
 
     Bug fixes
 
+      - zope.server.http: Connection: keep-alive wasn't sent
+        (http://zope.org/Collectors/Zope3-dev/714)
+
       - zope.pagetemplate.pagetemplatefile introspects the html http-equiv
         header to guess the content encoding. This did not work for XHTML
         content.

Modified: Zope3/trunk/src/zope/server/http/httptask.py
===================================================================
--- Zope3/trunk/src/zope/server/http/httptask.py	2007-03-10 12:34:07 UTC (rev 73135)
+++ Zope3/trunk/src/zope/server/http/httptask.py	2007-03-11 10:45:28 UTC (rev 73136)
@@ -116,6 +116,9 @@
         connection = self.request_data.headers.get('CONNECTION', '').lower()
         close_it = 0
         response_headers = self.response_headers
+        accumulated_headers = self.accumulated_headers
+        if accumulated_headers is None:
+            accumulated_headers = []
 
         if version == '1.0':
             if connection == 'keep-alive':
@@ -126,6 +129,9 @@
             else:
                 close_it = 1
         elif version == '1.1':
+            if 'connection: close' in (header.lower() for header in 
+                accumulated_headers):
+                close_it = 1
             if connection == 'close':
                 close_it = 1
             elif 'Transfer-Encoding' in response_headers:
@@ -135,7 +141,10 @@
                 # Replying with headers only.
                 pass
             elif not ('Content-Length' in response_headers):
-                close_it = 1
+                if 'content-length' not in (header.lower() for header in
+                    accumulated_headers):
+                    close_it = 1                
+            # under HTTP 1.1 keep-alive is default, no need to set the header
         else:
             # Close if unrecognized HTTP version.
             close_it = 1

Modified: Zope3/trunk/src/zope/server/http/tests/test_httpserver.py
===================================================================
--- Zope3/trunk/src/zope/server/http/tests/test_httpserver.py	2007-03-10 12:34:07 UTC (rev 73135)
+++ Zope3/trunk/src/zope/server/http/tests/test_httpserver.py	2007-03-11 10:45:28 UTC (rev 73136)
@@ -292,7 +292,83 @@
         response_body = response.read()
         self.failUnlessEqual(response_body, expect)
 
+    def testKeepaliveHttp10(self):
+        # Handling of Keep-Alive within HTTP 1.0
+        data = "Default: Don't keep me alive"
+        s = ("GET / HTTP/1.0\n"
+             "Content-Length: %d\n"
+             "\n"
+             "%s") % (len(data), data)
+        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        sock.connect((LOCALHOST, self.port))
+        sock.send(s)
+        response = ClientHTTPResponse(sock)
+        response.begin()
+        self.failUnlessEqual(int(response.status), 200)
+        connection = response.getheader('Connection', '')
+        # We sent no Connection: Keep-Alive header
+        # Connection: close (or no header) is default. 
+        self.failUnless(connection != 'Keep-Alive')
+        
+        # If header Connection: Keep-Alive is explicitly sent, 
+        # we want to keept the connection open, we also need to return
+        # the corresponding header
+        data = "Keep me alive"
+        s = ("GET / HTTP/1.0\n"
+             "Connection: Keep-Alive\n"
+             "Content-Length: %d\n"
+             "\n"
+             "%s") % (len(data), data)
+        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        sock.connect((LOCALHOST, self.port))
+        sock.send(s)
+        response = ClientHTTPResponse(sock)
+        response.begin()
+        self.failUnlessEqual(int(response.status), 200)
+        connection = response.getheader('Connection', '')
+        self.failUnlessEqual(connection, 'Keep-Alive')
 
+    def testKeepaliveHttp11(self):
+        # Handling of Keep-Alive within HTTP 1.1
+
+        # All connections are kept alive, unless stated otherwise
+        data = "Default: Keep me alive"
+        s = ("GET / HTTP/1.1\n"
+             "Content-Length: %d\n"
+             "\n"
+             "%s") % (len(data), data)
+        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        sock.connect((LOCALHOST, self.port))
+        sock.send(s)
+        response = ClientHTTPResponse(sock)
+        response.begin()
+        self.failUnlessEqual(int(response.status), 200)
+        self.failUnless(response.getheader('connection') != 'close')
+
+        # no idea why the test publisher handles this request incorrectly
+        # it would be less typing in the test :)
+        # h = HTTPConnection(LOCALHOST, self.port)
+        # h.request("GET", "/")
+        # response = h.getresponse()
+        # self.failUnlessEqual(int(response.status), 200)
+        # self.failUnless(response.getheader('connection') != 'close')
+ 
+        # specifying Connection: close explicitly 
+        data = "Don't keep me alive"
+        s = ("GET / HTTP/1.1\n"
+             "Connection: close\n"
+             "Content-Length: %d\n"
+             "\n"
+             "%s") % (len(data), data)
+        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        sock.connect((LOCALHOST, self.port))
+        sock.send(s)
+        response = ClientHTTPResponse(sock)
+        response.begin()
+        self.failUnlessEqual(int(response.status), 200)
+        self.failUnlessEqual(response.getheader('connection'), 'close')
+
+
 def test_suite():
     loader = unittest.TestLoader()
     return loader.loadTestsFromTestCase(Tests)



More information about the Zope3-Checkins mailing list