rendered paste body=== modified file 'twisted/web2/channel/http.py'
--- twisted/web2/channel/http.py 2007-01-01 23:41:33 +0000
+++ twisted/web2/channel/http.py 2008-03-20 16:58:30 +0000
@@ -10,7 +10,7 @@
from twisted.web2 import http_headers
from twisted.web2 import http
-PERSIST_NO_PIPELINE, PERSIST_PIPELINE = (1,2)
+PERSIST_NO_PIPELINE, PERSIST_PIPELINE = (False, True)
_cachedHostNames = {}
def _cachedGetHostByAddr(hostaddr):
@@ -55,7 +55,7 @@
inHeaders = None
partialHeader = ''
connHeaders = None
- finishedReading = False
+ finishedReading = True
channel = None
@@ -371,6 +371,7 @@
def gotInitialLine(self, initialLine):
+ self.finishedReading = False
parts = initialLine.split()
# Parse the initial request line
=== modified file 'twisted/web2/client/http.py'
--- twisted/web2/client/http.py 2007-10-19 08:16:52 +0000
+++ twisted/web2/client/http.py 2008-03-20 15:56:06 +0000
@@ -9,6 +9,7 @@
from zope.interface import implements
from twisted.internet.defer import Deferred
+from twisted.internet import error
from twisted.protocols.basic import LineReceiver
from twisted.protocols.policies import TimeoutMixin
@@ -168,6 +169,7 @@
self._error(reason)
def gotInitialLine(self, initialLine):
+ self.finishedReading = False
parts = initialLine.split(' ', 2)
# Parse the initial request line
@@ -350,7 +352,7 @@
if not persist:
# Tell all requests but first to abort.
for request in self.inRequests[1:]:
- request.connectionLost(None)
+ request.connectionLost(error.ConnectionDone())
del self.inRequests[1:]
def connectionLost(self, reason):
=== modified file 'twisted/web2/test/test_client.py'
--- twisted/web2/test/test_client.py 2007-10-19 08:16:52 +0000
+++ twisted/web2/test/test_client.py 2008-03-20 16:53:23 +0000
@@ -5,7 +5,7 @@
Tests for HTTP client.
"""
-from twisted.internet import protocol, defer
+from twisted.internet import protocol, defer, error
from twisted.web2.client import http
from twisted.web2 import http_headers
@@ -61,8 +61,10 @@
def assertReceived(self, cxn, expectedStatus, expectedHeaders,
expectedContent=None):
self.iterate(cxn)
-
- headers, content = cxn.server.data.split('\r\n\r\n', 1)
+
+ data = cxn.server.data
+ cxn.server.data = ''
+ headers, content = data.split('\r\n\r\n', 1)
status, headers = headers.split('\r\n', 1)
headers = headers.split('\r\n')
@@ -188,6 +190,54 @@
return d
+ def test_abortPipelining(self):
+ """
+ Ensure that pending requests are aborted if the server closes the
+ connection.
+ """
+
+ cxn = self.connect(inputTimeOut=None)
+ deferreds = []
+
+ req1 = http.ClientRequest('GET', '/', None, None)
+ d1 = cxn.client.submitRequest(req1, closeAfter=False).addCallback(
+ self.checkResponse, 200, [], 0, None)
+ deferreds.append(d1)
+
+ self.assertReceived(cxn, 'GET / HTTP/1.1',
+ ['Connection: Keep-Alive'])
+
+ self.writeLines(cxn, ('HTTP/1.1 200 OK',
+ 'Content-Length: 0',
+ 'Connection: Keep-Alive',
+ '\r\n'))
+
+ # pipeline two requests, after the first one the server closes the
+ # connection
+ req2 = http.ClientRequest('GET', '/', None, None)
+ d2 = cxn.client.submitRequest(req2, closeAfter=False).addCallback(
+ self.checkResponse, 200, [], 0, None)
+ deferreds.append(d2)
+
+ self.assertReceived(cxn, 'GET / HTTP/1.1',
+ ['Connection: Keep-Alive'])
+
+ req3 = http.ClientRequest('GET', '/', None, None)
+ d3 = cxn.client.submitRequest(req3, closeAfter=False)
+ self.failUnlessFailure(d3, error.ConnectionDone)
+ deferreds.append(d3)
+
+ self.assertReceived(cxn, 'GET / HTTP/1.1',
+ ['Connection: Keep-Alive'])
+
+ # close the connection, the client should cancel req3
+ self.writeLines(cxn, ('HTTP/1.1 200 OK',
+ 'Content-Length: 0',
+ 'Connection: close',
+ '\r\n'))
+
+ return defer.DeferredList(deferreds)
+
def test_userHeaders(self):
"""
Make sure that headers get through in both directions.