Skip to content

Commit 8cbc4bf

Browse files
authored
Merge pull request #3527 from bdarnell/backports-6.5.2
Backport bug fixes to 6.5 branch for 6.5.2
2 parents 38c6f59 + c0d3e6d commit 8cbc4bf

File tree

6 files changed

+39
-6
lines changed

6 files changed

+39
-6
lines changed

tornado/gen.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,20 @@ def __anext__(self) -> Future:
437437
return self.next()
438438

439439

440+
@overload
441+
def multi(
442+
children: Sequence[_Yieldable],
443+
quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = (),
444+
) -> Future[List]: ...
445+
446+
447+
@overload
448+
def multi(
449+
children: Mapping[Any, _Yieldable],
450+
quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = (),
451+
) -> Future[Dict]: ...
452+
453+
440454
def multi(
441455
children: Union[Sequence[_Yieldable], Mapping[Any, _Yieldable]],
442456
quiet_exceptions: "Union[Type[Exception], Tuple[Type[Exception], ...]]" = (),

tornado/http1connection.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ def __exit__(
6666
) -> None:
6767
if value is not None:
6868
assert typ is not None
69+
# Let HTTPInputError pass through to higher-level handler
70+
if isinstance(value, httputil.HTTPInputError):
71+
return None
6972
self.logger.error("Uncaught exception", exc_info=(typ, value, tb))
7073
raise _QuietException
7174

tornado/httputil.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,11 @@ class HTTPServerRequest:
459459
460460
.. versionchanged:: 4.0
461461
Moved from ``tornado.httpserver.HTTPRequest``.
462+
463+
.. deprecated:: 6.5.2
464+
The ``host`` argument to the ``HTTPServerRequest`` constructor is deprecated. Use
465+
``headers["Host"]`` instead. This argument was mistakenly removed in Tornado 6.5.0 and
466+
temporarily restored in 6.5.2.
462467
"""
463468

464469
path = None # type: str
@@ -474,7 +479,7 @@ def __init__(
474479
version: str = "HTTP/1.0",
475480
headers: Optional[HTTPHeaders] = None,
476481
body: Optional[bytes] = None,
477-
# host: Optional[str] = None,
482+
host: Optional[str] = None,
478483
files: Optional[Dict[str, List["HTTPFile"]]] = None,
479484
connection: Optional["HTTPConnection"] = None,
480485
start_line: Optional["RequestStartLine"] = None,
@@ -494,15 +499,14 @@ def __init__(
494499
self.protocol = getattr(context, "protocol", "http")
495500

496501
try:
497-
self.host = self.headers["Host"]
502+
self.host = host or self.headers["Host"]
498503
except KeyError:
499504
if version == "HTTP/1.0":
500505
# HTTP/1.0 does not require the Host header.
501506
self.host = "127.0.0.1"
502507
else:
503508
raise HTTPInputError("Missing Host header")
504509
if not _ABNF.host.fullmatch(self.host):
505-
print(_ABNF.host.pattern)
506510
raise HTTPInputError("Invalid Host header: %r" % self.host)
507511
if "," in self.host:
508512
# https://www.rfc-editor.org/rfc/rfc9112.html#name-request-target

tornado/routing.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ def finish(self) -> None:
279279
self.delegate.finish()
280280

281281
def on_connection_close(self) -> None:
282-
assert self.delegate is not None
283-
self.delegate.on_connection_close()
282+
if self.delegate is not None:
283+
self.delegate.on_connection_close()
284284

285285

286286
class _DefaultMessageDelegate(httputil.HTTPMessageDelegate):

tornado/test/httpclient_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ def test_invalid_gzip(self):
442442
# test if client hangs on tricky invalid gzip
443443
# curl/simple httpclient have different behavior (exception, logging)
444444
with ExpectLog(
445-
app_log, "(Uncaught exception|Exception in callback)", required=False
445+
gen_log, ".*Malformed HTTP message.*unconsumed gzip data", required=False
446446
):
447447
try:
448448
response = self.fetch("/invalid_gzip")

tornado/test/httpserver_test.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,18 @@ def test_malformed_headers(self):
462462
self.io_loop.add_timeout(datetime.timedelta(seconds=0.05), self.stop)
463463
self.wait()
464464

465+
def test_invalid_host_header_with_whitespace(self):
466+
with ExpectLog(
467+
gen_log, ".*Malformed HTTP message.*Invalid Host header", level=logging.INFO
468+
):
469+
self.stream.write(b"GET / HTTP/1.0\r\nHost: foo bar\r\n\r\n")
470+
start_line, headers, response = self.io_loop.run_sync(
471+
lambda: read_stream_body(self.stream)
472+
)
473+
self.assertEqual("HTTP/1.1", start_line.version)
474+
self.assertEqual(400, start_line.code)
475+
self.assertEqual("Bad Request", start_line.reason)
476+
465477
def test_chunked_request_body(self):
466478
# Chunked requests are not widely supported and we don't have a way
467479
# to generate them in AsyncHTTPClient, but HTTPServer will read them.

0 commit comments

Comments
 (0)