Upgrade locked dependency on Twisted to 24.7.0rc1. (#17502)
I also update the tests and HTTP Proxy code to fix it for this new Twisted release. Pulls in fix for https://github.com/twisted/twisted/security/advisories/GHSA-c8m8-j448-xjx7 Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
This commit is contained in:
parent
e8ee784c75
commit
8b449a8ce6
|
@ -0,0 +1 @@
|
||||||
|
Upgrade locked dependency on Twisted to 24.7.0rc1.
|
|
@ -1,4 +1,4 @@
|
||||||
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
|
# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "annotated-types"
|
name = "annotated-types"
|
||||||
|
@ -821,18 +821,21 @@ testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-chec
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "incremental"
|
name = "incremental"
|
||||||
version = "22.10.0"
|
version = "24.7.2"
|
||||||
description = "\"A small library that versions your Python projects.\""
|
description = "A small library that versions your Python projects."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "incremental-22.10.0-py2.py3-none-any.whl", hash = "sha256:b864a1f30885ee72c5ac2835a761b8fe8aa9c28b9395cacf27286602688d3e51"},
|
{file = "incremental-24.7.2-py3-none-any.whl", hash = "sha256:8cb2c3431530bec48ad70513931a760f446ad6c25e8333ca5d95e24b0ed7b8fe"},
|
||||||
{file = "incremental-22.10.0.tar.gz", hash = "sha256:912feeb5e0f7e0188e6f42241d2f450002e11bbc0937c65865045854c24c0bd0"},
|
{file = "incremental-24.7.2.tar.gz", hash = "sha256:fb4f1d47ee60efe87d4f6f0ebb5f70b9760db2b2574c59c8e8912be4ebd464c9"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
setuptools = ">=61.0"
|
||||||
|
tomli = {version = "*", markers = "python_version < \"3.11\""}
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
mypy = ["click (>=6.0)", "mypy (==0.812)", "twisted (>=16.4.0)"]
|
scripts = ["click (>=6.0)"]
|
||||||
scripts = ["click (>=6.0)", "twisted (>=16.4.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "isort"
|
name = "isort"
|
||||||
|
@ -2711,13 +2714,13 @@ urllib3 = ">=1.26.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "twisted"
|
name = "twisted"
|
||||||
version = "24.3.0"
|
version = "24.7.0rc1"
|
||||||
description = "An asynchronous networking framework written in Python"
|
description = "An asynchronous networking framework written in Python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8.0"
|
python-versions = ">=3.8.0"
|
||||||
files = [
|
files = [
|
||||||
{file = "twisted-24.3.0-py3-none-any.whl", hash = "sha256:039f2e6a49ab5108abd94de187fa92377abe5985c7a72d68d0ad266ba19eae63"},
|
{file = "twisted-24.7.0rc1-py3-none-any.whl", hash = "sha256:f37d6656fe4e2871fab29d8952ae90bd6ca8b48a9e4dfa1b348f4cd62e6ba0bb"},
|
||||||
{file = "twisted-24.3.0.tar.gz", hash = "sha256:6b38b6ece7296b5e122c9eb17da2eeab3d98a198f50ca9efd00fb03e5b4fd4ae"},
|
{file = "twisted-24.7.0rc1.tar.gz", hash = "sha256:bbc4a2193ca34cfa32f626300746698a6d70fcd77d9c0b79a664c347e39634fc"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
@ -2726,48 +2729,26 @@ automat = ">=0.8.0"
|
||||||
constantly = ">=15.1"
|
constantly = ">=15.1"
|
||||||
hyperlink = ">=17.1.1"
|
hyperlink = ">=17.1.1"
|
||||||
idna = {version = ">=2.4", optional = true, markers = "extra == \"tls\""}
|
idna = {version = ">=2.4", optional = true, markers = "extra == \"tls\""}
|
||||||
incremental = ">=22.10.0"
|
incremental = ">=24.7.0"
|
||||||
pyopenssl = {version = ">=21.0.0", optional = true, markers = "extra == \"tls\""}
|
pyopenssl = {version = ">=21.0.0", optional = true, markers = "extra == \"tls\""}
|
||||||
service-identity = {version = ">=18.1.0", optional = true, markers = "extra == \"tls\""}
|
service-identity = {version = ">=18.1.0", optional = true, markers = "extra == \"tls\""}
|
||||||
twisted-iocpsupport = {version = ">=1.0.2,<2", markers = "platform_system == \"Windows\""}
|
|
||||||
typing-extensions = ">=4.2.0"
|
typing-extensions = ">=4.2.0"
|
||||||
zope-interface = ">=5"
|
zope-interface = ">=5"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
all-non-platform = ["twisted[conch,http2,serial,test,tls]", "twisted[conch,http2,serial,test,tls]"]
|
all-non-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)"]
|
||||||
conch = ["appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)"]
|
conch = ["appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)"]
|
||||||
dev = ["coverage (>=6b1,<7)", "pyflakes (>=2.2,<3.0)", "python-subunit (>=1.4,<2.0)", "twisted[dev-release]", "twistedchecker (>=0.7,<1.0)"]
|
dev = ["coverage (>=7.5,<8.0)", "cython-test-exception-raiser (>=1.0.2,<2)", "hypothesis (>=6.56)", "pydoctor (>=23.9.0,<23.10.0)", "pyflakes (>=2.2,<3.0)", "pyhamcrest (>=2)", "python-subunit (>=1.4,<2.0)", "sphinx (>=6,<7)", "sphinx-rtd-theme (>=1.3,<2.0)", "towncrier (>=23.6,<24.0)", "twistedchecker (>=0.7,<1.0)"]
|
||||||
dev-release = ["pydoctor (>=23.9.0,<23.10.0)", "pydoctor (>=23.9.0,<23.10.0)", "sphinx (>=6,<7)", "sphinx (>=6,<7)", "sphinx-rtd-theme (>=1.3,<2.0)", "sphinx-rtd-theme (>=1.3,<2.0)", "towncrier (>=23.6,<24.0)", "towncrier (>=23.6,<24.0)"]
|
dev-release = ["pydoctor (>=23.9.0,<23.10.0)", "pydoctor (>=23.9.0,<23.10.0)", "sphinx (>=6,<7)", "sphinx (>=6,<7)", "sphinx-rtd-theme (>=1.3,<2.0)", "sphinx-rtd-theme (>=1.3,<2.0)", "towncrier (>=23.6,<24.0)", "towncrier (>=23.6,<24.0)"]
|
||||||
gtk-platform = ["pygobject", "pygobject", "twisted[all-non-platform]", "twisted[all-non-platform]"]
|
gtk-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pygobject", "pygobject", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)"]
|
||||||
http2 = ["h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)"]
|
http2 = ["h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)"]
|
||||||
macos-platform = ["pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "twisted[all-non-platform]", "twisted[all-non-platform]"]
|
macos-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)"]
|
||||||
mypy = ["mypy (>=1.8,<2.0)", "mypy-zope (>=1.0.3,<1.1.0)", "twisted[all-non-platform,dev]", "types-pyopenssl", "types-setuptools"]
|
mypy = ["appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "coverage (>=7.5,<8.0)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "idna (>=2.4)", "mypy (>=1.8,<2.0)", "mypy-zope (>=1.0.3,<1.1.0)", "priority (>=1.1.0,<2.0)", "pydoctor (>=23.9.0,<23.10.0)", "pyflakes (>=2.2,<3.0)", "pyhamcrest (>=2)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "python-subunit (>=1.4,<2.0)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "sphinx (>=6,<7)", "sphinx-rtd-theme (>=1.3,<2.0)", "towncrier (>=23.6,<24.0)", "twistedchecker (>=0.7,<1.0)", "types-pyopenssl", "types-setuptools"]
|
||||||
osx-platform = ["twisted[macos-platform]", "twisted[macos-platform]"]
|
osx-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)"]
|
||||||
serial = ["pyserial (>=3.0)", "pywin32 (!=226)"]
|
serial = ["pyserial (>=3.0)", "pywin32 (!=226)"]
|
||||||
test = ["cython-test-exception-raiser (>=1.0.2,<2)", "hypothesis (>=6.56)", "pyhamcrest (>=2)"]
|
test = ["cython-test-exception-raiser (>=1.0.2,<2)", "hypothesis (>=6.56)", "pyhamcrest (>=2)"]
|
||||||
tls = ["idna (>=2.4)", "pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)"]
|
tls = ["idna (>=2.4)", "pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)"]
|
||||||
windows-platform = ["pywin32 (!=226)", "pywin32 (!=226)", "twisted[all-non-platform]", "twisted[all-non-platform]"]
|
windows-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)", "twisted-iocpsupport (>=1.0.2)", "twisted-iocpsupport (>=1.0.2)"]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "twisted-iocpsupport"
|
|
||||||
version = "1.0.2"
|
|
||||||
description = "An extension for use in the twisted I/O Completion Ports reactor."
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "twisted-iocpsupport-1.0.2.tar.gz", hash = "sha256:72068b206ee809c9c596b57b5287259ea41ddb4774d86725b19f35bf56aa32a9"},
|
|
||||||
{file = "twisted_iocpsupport-1.0.2-cp310-cp310-win32.whl", hash = "sha256:985c06a33f5c0dae92c71a036d1ea63872ee86a21dd9b01e1f287486f15524b4"},
|
|
||||||
{file = "twisted_iocpsupport-1.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:81b3abe3527b367da0220482820cb12a16c661672b7bcfcde328902890d63323"},
|
|
||||||
{file = "twisted_iocpsupport-1.0.2-cp36-cp36m-win32.whl", hash = "sha256:9dbb8823b49f06d4de52721b47de4d3b3026064ef4788ce62b1a21c57c3fff6f"},
|
|
||||||
{file = "twisted_iocpsupport-1.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:b9fed67cf0f951573f06d560ac2f10f2a4bbdc6697770113a2fc396ea2cb2565"},
|
|
||||||
{file = "twisted_iocpsupport-1.0.2-cp37-cp37m-win32.whl", hash = "sha256:b76b4eed9b27fd63ddb0877efdd2d15835fdcb6baa745cb85b66e5d016ac2878"},
|
|
||||||
{file = "twisted_iocpsupport-1.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:851b3735ca7e8102e661872390e3bce88f8901bece95c25a0c8bb9ecb8a23d32"},
|
|
||||||
{file = "twisted_iocpsupport-1.0.2-cp38-cp38-win32.whl", hash = "sha256:bf4133139d77fc706d8f572e6b7d82871d82ec7ef25d685c2351bdacfb701415"},
|
|
||||||
{file = "twisted_iocpsupport-1.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:306becd6e22ab6e8e4f36b6bdafd9c92e867c98a5ce517b27fdd27760ee7ae41"},
|
|
||||||
{file = "twisted_iocpsupport-1.0.2-cp39-cp39-win32.whl", hash = "sha256:3c61742cb0bc6c1ac117a7e5f422c129832f0c295af49e01d8a6066df8cfc04d"},
|
|
||||||
{file = "twisted_iocpsupport-1.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:b435857b9efcbfc12f8c326ef0383f26416272260455bbca2cd8d8eca470c546"},
|
|
||||||
{file = "twisted_iocpsupport-1.0.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:7d972cfa8439bdcb35a7be78b7ef86d73b34b808c74be56dfa785c8a93b851bf"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "txredisapi"
|
name = "txredisapi"
|
||||||
|
|
|
@ -62,6 +62,15 @@ HOP_BY_HOP_HEADERS = {
|
||||||
"Upgrade",
|
"Upgrade",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hasattr(Headers, "_canonicalNameCaps"):
|
||||||
|
# Twisted < 24.7.0rc1
|
||||||
|
_canonicalHeaderName = Headers()._canonicalNameCaps # type: ignore[attr-defined]
|
||||||
|
else:
|
||||||
|
# Twisted >= 24.7.0rc1
|
||||||
|
# But note that `_encodeName` still exists on prior versions,
|
||||||
|
# it just encodes differently
|
||||||
|
_canonicalHeaderName = Headers()._encodeName
|
||||||
|
|
||||||
|
|
||||||
def parse_connection_header_value(
|
def parse_connection_header_value(
|
||||||
connection_header_value: Optional[bytes],
|
connection_header_value: Optional[bytes],
|
||||||
|
@ -85,11 +94,10 @@ def parse_connection_header_value(
|
||||||
The set of header names that should not be copied over from the remote response.
|
The set of header names that should not be copied over from the remote response.
|
||||||
The keys are capitalized in canonical capitalization.
|
The keys are capitalized in canonical capitalization.
|
||||||
"""
|
"""
|
||||||
headers = Headers()
|
|
||||||
extra_headers_to_remove: Set[str] = set()
|
extra_headers_to_remove: Set[str] = set()
|
||||||
if connection_header_value:
|
if connection_header_value:
|
||||||
extra_headers_to_remove = {
|
extra_headers_to_remove = {
|
||||||
headers._canonicalNameCaps(connection_option.strip()).decode("ascii")
|
_canonicalHeaderName(connection_option.strip()).decode("ascii")
|
||||||
for connection_option in connection_header_value.split(b",")
|
for connection_option in connection_header_value.split(b",")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@ from synapse.api.errors import (
|
||||||
from synapse.config.homeserver import HomeServerConfig
|
from synapse.config.homeserver import HomeServerConfig
|
||||||
from synapse.logging.context import defer_to_thread, preserve_fn, run_in_background
|
from synapse.logging.context import defer_to_thread, preserve_fn, run_in_background
|
||||||
from synapse.logging.opentracing import active_span, start_active_span, trace_servlet
|
from synapse.logging.opentracing import active_span, start_active_span, trace_servlet
|
||||||
|
from synapse.types import ISynapseReactor
|
||||||
from synapse.util import json_encoder
|
from synapse.util import json_encoder
|
||||||
from synapse.util.caches import intern_dict
|
from synapse.util.caches import intern_dict
|
||||||
from synapse.util.cancellation import is_function_cancellable
|
from synapse.util.cancellation import is_function_cancellable
|
||||||
|
@ -868,7 +869,8 @@ async def _async_write_json_to_request_in_thread(
|
||||||
|
|
||||||
with start_active_span("encode_json_response"):
|
with start_active_span("encode_json_response"):
|
||||||
span = active_span()
|
span = active_span()
|
||||||
json_str = await defer_to_thread(request.reactor, encode, span)
|
reactor: ISynapseReactor = request.reactor # type: ignore
|
||||||
|
json_str = await defer_to_thread(reactor, encode, span)
|
||||||
|
|
||||||
_write_bytes_to_request(request, json_str)
|
_write_bytes_to_request(request, json_str)
|
||||||
|
|
||||||
|
|
|
@ -683,7 +683,7 @@ class SynapseSite(ProxySite):
|
||||||
self.access_logger = logging.getLogger(logger_name)
|
self.access_logger = logging.getLogger(logger_name)
|
||||||
self.server_version_string = server_version_string.encode("ascii")
|
self.server_version_string = server_version_string.encode("ascii")
|
||||||
|
|
||||||
def log(self, request: SynapseRequest) -> None:
|
def log(self, request: SynapseRequest) -> None: # type: ignore[override]
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -969,9 +969,8 @@ class CASTestCase(unittest.HomeserverTestCase):
|
||||||
# Test that the response is HTML.
|
# Test that the response is HTML.
|
||||||
self.assertEqual(channel.code, 200, channel.result)
|
self.assertEqual(channel.code, 200, channel.result)
|
||||||
content_type_header_value = ""
|
content_type_header_value = ""
|
||||||
for header in channel.result.get("headers", []):
|
for header in channel.headers.getRawHeaders("Content-Type", []):
|
||||||
if header[0] == b"Content-Type":
|
content_type_header_value = header
|
||||||
content_type_header_value = header[1].decode("utf8")
|
|
||||||
|
|
||||||
self.assertTrue(content_type_header_value.startswith("text/html"))
|
self.assertTrue(content_type_header_value.startswith("text/html"))
|
||||||
|
|
||||||
|
|
|
@ -198,17 +198,35 @@ class FakeChannel:
|
||||||
def headers(self) -> Headers:
|
def headers(self) -> Headers:
|
||||||
if not self.result:
|
if not self.result:
|
||||||
raise Exception("No result yet.")
|
raise Exception("No result yet.")
|
||||||
h = Headers()
|
|
||||||
for i in self.result["headers"]:
|
h = self.result["headers"]
|
||||||
h.addRawHeader(*i)
|
assert isinstance(h, Headers)
|
||||||
return h
|
return h
|
||||||
|
|
||||||
def writeHeaders(
|
def writeHeaders(
|
||||||
self, version: bytes, code: bytes, reason: bytes, headers: Headers
|
self,
|
||||||
|
version: bytes,
|
||||||
|
code: bytes,
|
||||||
|
reason: bytes,
|
||||||
|
headers: Union[Headers, List[Tuple[bytes, bytes]]],
|
||||||
) -> None:
|
) -> None:
|
||||||
self.result["version"] = version
|
self.result["version"] = version
|
||||||
self.result["code"] = code
|
self.result["code"] = code
|
||||||
self.result["reason"] = reason
|
self.result["reason"] = reason
|
||||||
|
|
||||||
|
if isinstance(headers, list):
|
||||||
|
# Support prior to Twisted 24.7.0rc1
|
||||||
|
new_headers = Headers()
|
||||||
|
for k, v in headers:
|
||||||
|
assert isinstance(k, bytes), f"key is not of type bytes: {k!r}"
|
||||||
|
assert isinstance(v, bytes), f"value is not of type bytes: {v!r}"
|
||||||
|
new_headers.addRawHeader(k, v)
|
||||||
|
headers = new_headers
|
||||||
|
|
||||||
|
assert isinstance(
|
||||||
|
headers, Headers
|
||||||
|
), f"headers are of the wrong type: {headers!r}"
|
||||||
|
|
||||||
self.result["headers"] = headers
|
self.result["headers"] = headers
|
||||||
|
|
||||||
def write(self, data: bytes) -> None:
|
def write(self, data: bytes) -> None:
|
||||||
|
|
|
@ -392,8 +392,7 @@ class WrapHtmlRequestHandlerTests(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(channel.code, 301)
|
self.assertEqual(channel.code, 301)
|
||||||
headers = channel.result["headers"]
|
location_headers = channel.headers.getRawHeaders(b"Location", [])
|
||||||
location_headers = [v for k, v in headers if k == b"Location"]
|
|
||||||
self.assertEqual(location_headers, [b"/look/an/eagle"])
|
self.assertEqual(location_headers, [b"/look/an/eagle"])
|
||||||
|
|
||||||
def test_redirect_exception_with_cookie(self) -> None:
|
def test_redirect_exception_with_cookie(self) -> None:
|
||||||
|
@ -415,10 +414,10 @@ class WrapHtmlRequestHandlerTests(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(channel.code, 304)
|
self.assertEqual(channel.code, 304)
|
||||||
headers = channel.result["headers"]
|
headers = channel.headers
|
||||||
location_headers = [v for k, v in headers if k == b"Location"]
|
location_headers = headers.getRawHeaders(b"Location", [])
|
||||||
self.assertEqual(location_headers, [b"/no/over/there"])
|
self.assertEqual(location_headers, [b"/no/over/there"])
|
||||||
cookies_headers = [v for k, v in headers if k == b"Set-Cookie"]
|
cookies_headers = headers.getRawHeaders(b"Set-Cookie", [])
|
||||||
self.assertEqual(cookies_headers, [b"session=yespls"])
|
self.assertEqual(cookies_headers, [b"session=yespls"])
|
||||||
|
|
||||||
def test_head_request(self) -> None:
|
def test_head_request(self) -> None:
|
||||||
|
|
Loading…
Reference in New Issue