From: Ben Darnell Date: Fri, 7 Jun 2024 18:42:28 +0000 (-0400) Subject: httputil: Add types for elements of HTTPHeaders X-Git-Tag: v6.5.0b1~58^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e7dff512f8329dfc92590f144abbeaff55fce6ad;p=thirdparty%2Ftornado.git httputil: Add types for elements of HTTPHeaders Revealed an issue in websocket.py in which bytes were used when it should have been str. This avoided being a bug because something down the line was converting it to str but it was still a logical type error. The change to httputil.py was taken from #3329 (thanks mslynch). Closes #3329 Fixes #3328 --- diff --git a/tornado/httputil.py b/tornado/httputil.py index 9ce992d8..81550353 100644 --- a/tornado/httputil.py +++ b/tornado/httputil.py @@ -62,6 +62,12 @@ if typing.TYPE_CHECKING: from asyncio import Future # noqa: F401 import unittest # noqa: F401 + # This can be done unconditionally in the base class of HTTPHeaders + # after we drop support for Python 3.8. + StrMutableMapping = collections.abc.MutableMapping[str, str] +else: + StrMutableMapping = collections.abc.MutableMapping + # To be used with str.strip() and related methods. HTTP_WHITESPACE = " \t" @@ -76,7 +82,7 @@ def _normalize_header(name: str) -> str: return "-".join([w.capitalize() for w in name.split("-")]) -class HTTPHeaders(collections.abc.MutableMapping): +class HTTPHeaders(StrMutableMapping): """A dictionary that maintains ``Http-Header-Case`` for all keys. Supports multiple values per key via a pair of new methods, diff --git a/tornado/web.py b/tornado/web.py index 03939647..21d0cad6 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -1596,14 +1596,14 @@ class RequestHandler(object): # information please see # http://www.djangoproject.com/weblog/2011/feb/08/security/ # http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails - token = ( + input_token = ( self.get_argument("_xsrf", None) or self.request.headers.get("X-Xsrftoken") or self.request.headers.get("X-Csrftoken") ) - if not token: + if not input_token: raise HTTPError(403, "'_xsrf' argument missing from POST") - _, token, _ = self._decode_xsrf_token(token) + _, token, _ = self._decode_xsrf_token(input_token) _, expected_token, _ = self._get_raw_xsrf_token() if not token: raise HTTPError(403, "'_xsrf' argument has invalid format") diff --git a/tornado/websocket.py b/tornado/websocket.py index 8f0e0aef..01273030 100644 --- a/tornado/websocket.py +++ b/tornado/websocket.py @@ -1380,7 +1380,7 @@ class WebSocketClientConnection(simple_httpclient._HTTPConnection): { "Upgrade": "websocket", "Connection": "Upgrade", - "Sec-WebSocket-Key": self.key, + "Sec-WebSocket-Key": to_unicode(self.key), "Sec-WebSocket-Version": "13", } )