Nicer error message when timing out waiting for a chunk

This commit is contained in:
Kovid Goyal 2015-05-20 11:14:11 +05:30
parent 97c59251bb
commit 8cc8d83a38
3 changed files with 24 additions and 4 deletions

View File

@ -247,7 +247,10 @@ class ChunkedReader(object): # {{{
raise BadChunkedInput('%s is not a valid chunk size' % reprlib.repr(chunk_size)) raise BadChunkedInput('%s is not a valid chunk size' % reprlib.repr(chunk_size))
if chunk_size + self.bytes_read > self.maxsize: if chunk_size + self.bytes_read > self.maxsize:
raise MaxSizeExceeded('Request entity too large', self.bytes_read + chunk_size, self.maxsize) raise MaxSizeExceeded('Request entity too large', self.bytes_read + chunk_size, self.maxsize)
try:
chunk = self.socket_file.read(chunk_size) chunk = self.socket_file.read(chunk_size)
except socket.timeout:
raise BadChunkedInput('Timed out waiting for chunk of size %d to complete' % chunk_size)
if len(chunk) < chunk_size: if len(chunk) < chunk_size:
raise BadChunkedInput('Bad chunked encoding, chunk truncated: %d < %s' % (len(chunk), chunk_size)) raise BadChunkedInput('Bad chunked encoding, chunk truncated: %d < %s' % (len(chunk), chunk_size))
if not chunk.endswith(b'\r\n'): if not chunk.endswith(b'\r\n'):

View File

@ -61,8 +61,8 @@ class TestServer(Thread):
def __exit__(self, *args): def __exit__(self, *args):
self.loop.stop() self.loop.stop()
def connect(self): def connect(self, timeout=0.1):
return httplib.HTTPConnection(self.address[0], self.address[1], strict=True, timeout=0.1) return httplib.HTTPConnection(self.address[0], self.address[1], strict=True, timeout=timeout)
def change_handler(self, handler): def change_handler(self, handler):
from calibre.srv.http import create_http_handler from calibre.srv.http import create_http_handler

View File

@ -64,7 +64,7 @@ class TestHTTP(BaseTest):
body = 'Requested resource not found' body = 'Requested resource not found'
def handler(conn): def handler(conn):
raise HTTP404(body) raise HTTP404(body)
with TestServer(handler, max_header_line_size=100./1024, max_request_body_size=100./(1024*1024)) as server: with TestServer(handler, timeout=0.1, max_header_line_size=100./1024, max_request_body_size=100./(1024*1024)) as server:
# Test 404 # Test 404
conn = server.connect() conn = server.connect()
conn.request('HEAD', '/moose') conn.request('HEAD', '/moose')
@ -109,14 +109,31 @@ class TestHTTP(BaseTest):
r = conn.getresponse() r = conn.getresponse()
self.ae(r.status, httplib.BAD_REQUEST) self.ae(r.status, httplib.BAD_REQUEST)
conn = server.connect()
conn.request('GET', '/test', ('a' * 200)) conn.request('GET', '/test', ('a' * 200))
r = conn.getresponse() r = conn.getresponse()
self.ae(r.status, httplib.REQUEST_ENTITY_TOO_LARGE) self.ae(r.status, httplib.REQUEST_ENTITY_TOO_LARGE)
conn = server.connect()
conn.request('POST', '/test', headers={'Transfer-Encoding': 'chunked'}) conn.request('POST', '/test', headers={'Transfer-Encoding': 'chunked'})
conn.send(b'x\r\nbody\r\n0\r\n\r\n') conn.send(b'x\r\nbody\r\n0\r\n\r\n')
r = conn.getresponse() r = conn.getresponse()
self.ae(r.status, httplib.BAD_REQUEST) self.ae(r.status, httplib.BAD_REQUEST)
self.assertIn(b'not a valid chunk size', r.read())
conn = server.connect()
conn.request('POST', '/test', headers={'Transfer-Encoding': 'chunked'})
conn.send(b'3\r\nbody\r\n0\r\n\r\n')
r = conn.getresponse()
self.ae(r.status, httplib.BAD_REQUEST)
self.assertIn(b'!= CRLF', r.read())
conn = server.connect(timeout=1)
conn.request('POST', '/test', headers={'Transfer-Encoding': 'chunked'})
conn.send(b'30\r\nbody\r\n0\r\n\r\n')
r = conn.getresponse()
self.ae(r.status, httplib.BAD_REQUEST)
self.assertIn(b'Timed out waiting for chunk', r.read())
server.log.filter_level = orig_level server.log.filter_level = orig_level
conn = server.connect() conn = server.connect()