) -> None:
if value is not None:
assert typ is not None
+ # Let HTTPInputError pass through to higher-level handler
+ if isinstance(value, httputil.HTTPInputError):
+ return None
self.logger.error("Uncaught exception", exc_info=(typ, value, tb))
raise _QuietException
self.delegate.finish()
def on_connection_close(self) -> None:
- assert self.delegate is not None
- self.delegate.on_connection_close()
+ if self.delegate is not None:
+ self.delegate.on_connection_close()
class _DefaultMessageDelegate(httputil.HTTPMessageDelegate):
# test if client hangs on tricky invalid gzip
# curl/simple httpclient have different behavior (exception, logging)
with ExpectLog(
- app_log, "(Uncaught exception|Exception in callback)", required=False
+ gen_log, ".*Malformed HTTP message.*unconsumed gzip data", required=False
):
try:
response = self.fetch("/invalid_gzip")
self.io_loop.add_timeout(datetime.timedelta(seconds=0.05), self.stop)
self.wait()
+ def test_invalid_host_header_with_whitespace(self):
+ with ExpectLog(
+ gen_log, ".*Malformed HTTP message.*Invalid Host header", level=logging.INFO
+ ):
+ self.stream.write(b"GET / HTTP/1.0\r\nHost: foo bar\r\n\r\n")
+ start_line, headers, response = self.io_loop.run_sync(
+ lambda: read_stream_body(self.stream)
+ )
+ self.assertEqual("HTTP/1.1", start_line.version)
+ self.assertEqual(400, start_line.code)
+ self.assertEqual("Bad Request", start_line.reason)
+
def test_chunked_request_body(self):
# Chunked requests are not widely supported and we don't have a way
# to generate them in AsyncHTTPClient, but HTTPServer will read them.