r47342 - apply patch from lukasa, refs #8317
hawkowl-TA+aISz0psMTMxyoc4vAAJOcrHinNvQL0E9HWUfgJXw@public.gmane.org Wed, 4 May 2016 05:58:51 -0600 (MDT)
| Newsgroups | gmane.comp.python.twisted.commits |
|---|---|
| Message-ID | <[email protected]> |
Author: hawkowl
Date: Wed May 4 05:58:45 2016
New Revision: 47342
Added:
branches/why-stop-a-request-when-you-can-keep-writing-8317/twisted/web/topfiles/8317.bugfix
Modified:
branches/why-stop-a-request-when-you-can-keep-writing-8317/twisted/web/http.py
branches/why-stop-a-request-when-you-can-keep-writing-8317/twisted/web/test/test_http.py
Log:
apply patch from lukasa, refs #8317
Modified: branches/why-stop-a-request-when-you-can-keep-writing-8317/twisted/web/http.py
==============================================================================
--- branches/why-stop-a-request-when-you-can-keep-writing-8317/twisted/web/http.py (original)
+++ branches/why-stop-a-request-when-you-can-keep-writing-8317/twisted/web/http.py Wed May 4 05:58:45 2016
@@ -1681,7 +1681,11 @@
elif line == b'':
# End of headers.
if self.__header:
- self.headerReceived(self.__header)
+ ok = self.headerReceived(self.__header)
+ # If the last header we got is invalid, we MUST NOT proceed
+ # with processing. We'll have sent a 400 anyway, so just stop.
+ if not ok:
+ return
self.__header = ''
self.allHeadersReceived()
if self.length == 0:
@@ -1713,12 +1717,15 @@
@type line: C{bytes}
@param line: A line from the header section of a request, excluding the
line delimiter.
+
+ @return: A flag indicating whether the header was valid.
+ @rtype: L{bool}
"""
try:
header, data = line.split(b':', 1)
except ValueError:
_respondToBadRequestAndDisconnect(self.transport)
- return
+ return False
header = header.lower()
data = data.strip()
@@ -1728,7 +1735,7 @@
except ValueError:
_respondToBadRequestAndDisconnect(self.transport)
self.length = None
- return
+ return False
self._transferDecoder = _IdentityTransferDecoder(
self.length, self.requests[-1].handleContentChunk, self._finishRequestBody)
elif header == b'transfer-encoding' and data.lower() == b'chunked':
@@ -1747,7 +1754,9 @@
self._receivedHeaderCount += 1
if self._receivedHeaderCount > self.maxHeaders:
_respondToBadRequestAndDisconnect(self.transport)
- return
+ return False
+
+ return True
def allContentReceived(self):
Modified: branches/why-stop-a-request-when-you-can-keep-writing-8317/twisted/web/test/test_http.py
==============================================================================
--- branches/why-stop-a-request-when-you-can-keep-writing-8317/twisted/web/test/test_http.py (original)
+++ branches/why-stop-a-request-when-you-can-keep-writing-8317/twisted/web/test/test_http.py Wed May 4 05:58:45 2016
@@ -812,12 +812,19 @@
When client sends invalid HTTP method containing
non-ascii characters HTTP 400 'Bad Request' status will be returned.
"""
+ processed = []
+ class MyRequest(http.Request):
+ def process(self):
+ processed.append(self)
+ self.finish()
+
badRequestLine = b"GE\xc2\xa9 / HTTP/1.1\r\n\r\n"
- channel = self.runRequest(badRequestLine, http.Request, 0)
+ channel = self.runRequest(badRequestLine, MyRequest, 0)
self.assertEqual(
channel.transport.value(),
b"HTTP/1.1 400 Bad Request\r\n\r\n")
self.assertTrue(channel.transport.disconnecting)
+ self.assertEqual(processed, [])
def test_basicAuth(self):
@@ -895,12 +902,19 @@
(Bad Request) response is sent to the client and the connection is
closed.
"""
+ processed = []
+ class MyRequest(http.Request):
+ def process(self):
+ processed.append(self)
+ self.finish()
+
requestLines = [b"GET / HTTP/1.0", b"Content-Length: x", b"", b""]
- channel = self.runRequest(b"\n".join(requestLines), http.Request, 0)
+ channel = self.runRequest(b"\n".join(requestLines), MyRequest, 0)
self.assertEqual(
channel.transport.value(),
b"HTTP/1.1 400 Bad Request\r\n\r\n")
self.assertTrue(channel.transport.disconnecting)
+ self.assertEqual(processed, [])
def test_invalidHeaderNoColon(self):
@@ -908,12 +922,19 @@
If a header without colon is received a 400 (Bad Request) response
is sent to the client and the connection is closed.
"""
+ processed = []
+ class MyRequest(http.Request):
+ def process(self):
+ processed.append(self)
+ self.finish()
+
requestLines = [b"GET / HTTP/1.0", b"HeaderName ", b"", b""]
- channel = self.runRequest(b"\n".join(requestLines), http.Request, 0)
+ channel = self.runRequest(b"\n".join(requestLines), MyRequest, 0)
self.assertEqual(
channel.transport.value(),
b"HTTP/1.1 400 Bad Request\r\n\r\n")
self.assertTrue(channel.transport.disconnecting)
+ self.assertEqual(processed, [])
def test_headerLimitPerRequest(self):
@@ -963,13 +984,24 @@
on the size of headers received per request starting from initial
command line.
"""
+ processed = []
+ class MyRequest(http.Request):
+ def process(self):
+ processed.append(self)
+ self.finish()
+
channel = http.HTTPChannel()
channel.totalHeadersSize = 10
httpRequest = b'GET /path/longer/than/10 HTTP/1.1\n'
channel = self.runRequest(
- httpRequest=httpRequest, channel=channel, success=False)
+ httpRequest=httpRequest,
+ requestFactory=MyRequest,
+ channel=channel,
+ success=False
+ )
+ self.assertEqual(processed, [])
self.assertEqual(
channel.transport.value(),
b"HTTP/1.1 400 Bad Request\r\n\r\n")
@@ -981,6 +1013,12 @@
on the size of headers received per request counting first line
and total headers.
"""
+ processed = []
+ class MyRequest(http.Request):
+ def process(self):
+ processed.append(self)
+ self.finish()
+
channel = http.HTTPChannel()
channel.totalHeadersSize = 40
httpRequest = (
@@ -989,8 +1027,12 @@
)
channel = self.runRequest(
- httpRequest=httpRequest, channel=channel, success=False)
+ httpRequest=httpRequest,
+ requestFactory=MyRequest,
+ channel=channel, success=False
+ )
+ self.assertEqual(processed, [])
self.assertEqual(
channel.transport.value(),
b"HTTP/1.1 400 Bad Request\r\n\r\n")