From a37c4f28b7e3a4d19de283b36133abf9f4cb73cc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 27 Nov 2024 10:57:28 -0800 Subject: [PATCH 1/8] Increment version to 3.11.9.dev0 (#10069) --- aiohttp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiohttp/__init__.py b/aiohttp/__init__.py index 32273ac23b0..7896648923e 100644 --- a/aiohttp/__init__.py +++ b/aiohttp/__init__.py @@ -1,4 +1,4 @@ -__version__ = "3.11.8" +__version__ = "3.11.9.dev0" from typing import TYPE_CHECKING, Tuple From 8b08c9e4c733961a7fbb14446fd3c9a5a9a55229 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 1 Dec 2024 15:12:54 -0600 Subject: [PATCH 2/8] [PR #10078/0d6a83e backport][3.11] Bump yarl to 1.18.3 (#10079) --- requirements/base.txt | 2 +- requirements/constraints.txt | 2 +- requirements/dev.txt | 2 +- requirements/runtime-deps.txt | 2 +- requirements/test.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements/base.txt b/requirements/base.txt index ec2e6399590..1e7c0bbe6c1 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -44,5 +44,5 @@ typing-extensions==4.12.2 # via multidict uvloop==0.21.0 ; platform_system != "Windows" and implementation_name == "cpython" # via -r requirements/base.in -yarl==1.17.1 +yarl==1.18.3 # via -r requirements/runtime-deps.in diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 20b1705e6a7..d32acc7b773 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -306,7 +306,7 @@ wait-for-it==2.2.2 # via -r requirements/test.in wheel==0.44.0 # via pip-tools -yarl==1.17.1 +yarl==1.18.3 # via -r requirements/runtime-deps.in zipp==3.20.2 # via diff --git a/requirements/dev.txt b/requirements/dev.txt index 2c7da214ab2..168ce639d19 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -277,7 +277,7 @@ wait-for-it==2.2.2 # via -r requirements/test.in wheel==0.44.0 # via pip-tools -yarl==1.17.1 +yarl==1.18.3 # via -r requirements/runtime-deps.in zipp==3.20.2 # via diff --git a/requirements/runtime-deps.txt b/requirements/runtime-deps.txt index 553347e35dd..cf7f0e396f6 100644 --- a/requirements/runtime-deps.txt +++ b/requirements/runtime-deps.txt @@ -38,5 +38,5 @@ pycparser==2.22 # via cffi typing-extensions==4.12.2 # via multidict -yarl==1.17.1 +yarl==1.18.3 # via -r requirements/runtime-deps.in diff --git a/requirements/test.txt b/requirements/test.txt index 95551d58600..33510f18682 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -155,5 +155,5 @@ uvloop==0.21.0 ; platform_system != "Windows" and implementation_name == "cpytho # via -r requirements/base.in wait-for-it==2.2.2 # via -r requirements/test.in -yarl==1.17.1 +yarl==1.18.3 # via -r requirements/runtime-deps.in From b849326eeeba6855e80e1be19c5c0a8bcb21bb10 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 1 Dec 2024 15:26:26 -0600 Subject: [PATCH 3/8] [PR #10078/0d6a83e backport][3.12] Bump yarl to 1.18.3 (#10080) --- requirements/base.txt | 2 +- requirements/constraints.txt | 2 +- requirements/dev.txt | 2 +- requirements/runtime-deps.txt | 2 +- requirements/test.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements/base.txt b/requirements/base.txt index ec2e6399590..1e7c0bbe6c1 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -44,5 +44,5 @@ typing-extensions==4.12.2 # via multidict uvloop==0.21.0 ; platform_system != "Windows" and implementation_name == "cpython" # via -r requirements/base.in -yarl==1.17.1 +yarl==1.18.3 # via -r requirements/runtime-deps.in diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 20b1705e6a7..d32acc7b773 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -306,7 +306,7 @@ wait-for-it==2.2.2 # via -r requirements/test.in wheel==0.44.0 # via pip-tools -yarl==1.17.1 +yarl==1.18.3 # via -r requirements/runtime-deps.in zipp==3.20.2 # via diff --git a/requirements/dev.txt b/requirements/dev.txt index 2c7da214ab2..168ce639d19 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -277,7 +277,7 @@ wait-for-it==2.2.2 # via -r requirements/test.in wheel==0.44.0 # via pip-tools -yarl==1.17.1 +yarl==1.18.3 # via -r requirements/runtime-deps.in zipp==3.20.2 # via diff --git a/requirements/runtime-deps.txt b/requirements/runtime-deps.txt index 553347e35dd..cf7f0e396f6 100644 --- a/requirements/runtime-deps.txt +++ b/requirements/runtime-deps.txt @@ -38,5 +38,5 @@ pycparser==2.22 # via cffi typing-extensions==4.12.2 # via multidict -yarl==1.17.1 +yarl==1.18.3 # via -r requirements/runtime-deps.in diff --git a/requirements/test.txt b/requirements/test.txt index 95551d58600..33510f18682 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -155,5 +155,5 @@ uvloop==0.21.0 ; platform_system != "Windows" and implementation_name == "cpytho # via -r requirements/base.in wait-for-it==2.2.2 # via -r requirements/test.in -yarl==1.17.1 +yarl==1.18.3 # via -r requirements/runtime-deps.in From da9210bde9540a49a75c1f3ba3bc332e3ee47823 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 21:32:25 +0000 Subject: [PATCH 4/8] [PR #10076/fad44f6b backport][3.11] Fix request count check for BadHttpMethod (#10081) Co-authored-by: J. Nick Koston --- CHANGES/10055.bugfix.rst | 1 + CHANGES/10076.bugfix.rst | 1 + aiohttp/web_protocol.py | 7 ++----- aiohttp/web_server.py | 2 ++ tests/test_web_server.py | 14 ++++++++++++++ 5 files changed, 20 insertions(+), 5 deletions(-) create mode 120000 CHANGES/10055.bugfix.rst create mode 100644 CHANGES/10076.bugfix.rst diff --git a/CHANGES/10055.bugfix.rst b/CHANGES/10055.bugfix.rst new file mode 120000 index 00000000000..b1f45d8b887 --- /dev/null +++ b/CHANGES/10055.bugfix.rst @@ -0,0 +1 @@ +10076.bugfix.rst \ No newline at end of file diff --git a/CHANGES/10076.bugfix.rst b/CHANGES/10076.bugfix.rst new file mode 100644 index 00000000000..c577366bbe8 --- /dev/null +++ b/CHANGES/10076.bugfix.rst @@ -0,0 +1 @@ +Fixed invalid method logging unexpected being logged at exception level on subsequent connections -- by :user:`bdraco`. diff --git a/aiohttp/web_protocol.py b/aiohttp/web_protocol.py index fe2ae8a1269..e8bb41abf97 100644 --- a/aiohttp/web_protocol.py +++ b/aiohttp/web_protocol.py @@ -192,6 +192,7 @@ def __init__( ): super().__init__(loop) + # _request_count is the number of requests processed with the same connection. self._request_count = 0 self._keepalive = False self._current_request: Optional[BaseRequest] = None @@ -688,11 +689,7 @@ def handle_error( Returns HTTP response with specific status code. Logs additional information. It always closes current connection. """ - if ( - self._manager - and self._manager.requests_count == 1 - and isinstance(exc, BadHttpMethod) - ): + if self._request_count == 1 and isinstance(exc, BadHttpMethod): # BadHttpMethod is common when a client sends non-HTTP # or encrypted traffic to an HTTP port. This is expected # to happen when connected to the public internet so we log diff --git a/aiohttp/web_server.py b/aiohttp/web_server.py index b6ac25ac1a5..328aca1e405 100644 --- a/aiohttp/web_server.py +++ b/aiohttp/web_server.py @@ -25,6 +25,8 @@ def __init__( self._loop = loop or asyncio.get_running_loop() self._connections: Dict[RequestHandler, asyncio.Transport] = {} self._kwargs = kwargs + # requests_count is the number of requests being processed by the server + # for the lifetime of the server. self.requests_count = 0 self.request_handler = handler self.request_factory = request_factory or self._make_request diff --git a/tests/test_web_server.py b/tests/test_web_server.py index e77df623020..7b9b87a374a 100644 --- a/tests/test_web_server.py +++ b/tests/test_web_server.py @@ -86,6 +86,20 @@ async def handler(request: web.BaseRequest) -> NoReturn: # be probing for TLS/SSL support which is # expected to fail logger.debug.assert_called_with("Error handling request", exc_info=exc) + logger.debug.reset_mock() + + # Now make another connection to the server + # to make sure that the exception is logged + # at debug on a second fresh connection + cli2 = await aiohttp_client(server) + resp = await cli2.get("/path/to") + assert resp.status == 500 + assert resp.headers["Content-Type"].startswith("text/plain") + # BadHttpMethod should be logged as debug + # on the first request since the client may + # be probing for TLS/SSL support which is + # expected to fail + logger.debug.assert_called_with("Error handling request", exc_info=exc) async def test_raw_server_logs_invalid_method_without_loop_debug( From 2b2301fcdc70010a3c39ff060901f2d1e65bbdfe Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 21:51:00 +0000 Subject: [PATCH 5/8] [PR #10076/fad44f6b backport][3.12] Fix request count check for BadHttpMethod (#10082) Co-authored-by: J. Nick Koston --- CHANGES/10055.bugfix.rst | 1 + CHANGES/10076.bugfix.rst | 1 + aiohttp/web_protocol.py | 7 ++----- aiohttp/web_server.py | 2 ++ tests/test_web_server.py | 14 ++++++++++++++ 5 files changed, 20 insertions(+), 5 deletions(-) create mode 120000 CHANGES/10055.bugfix.rst create mode 100644 CHANGES/10076.bugfix.rst diff --git a/CHANGES/10055.bugfix.rst b/CHANGES/10055.bugfix.rst new file mode 120000 index 00000000000..b1f45d8b887 --- /dev/null +++ b/CHANGES/10055.bugfix.rst @@ -0,0 +1 @@ +10076.bugfix.rst \ No newline at end of file diff --git a/CHANGES/10076.bugfix.rst b/CHANGES/10076.bugfix.rst new file mode 100644 index 00000000000..c577366bbe8 --- /dev/null +++ b/CHANGES/10076.bugfix.rst @@ -0,0 +1 @@ +Fixed invalid method logging unexpected being logged at exception level on subsequent connections -- by :user:`bdraco`. diff --git a/aiohttp/web_protocol.py b/aiohttp/web_protocol.py index fe2ae8a1269..e8bb41abf97 100644 --- a/aiohttp/web_protocol.py +++ b/aiohttp/web_protocol.py @@ -192,6 +192,7 @@ def __init__( ): super().__init__(loop) + # _request_count is the number of requests processed with the same connection. self._request_count = 0 self._keepalive = False self._current_request: Optional[BaseRequest] = None @@ -688,11 +689,7 @@ def handle_error( Returns HTTP response with specific status code. Logs additional information. It always closes current connection. """ - if ( - self._manager - and self._manager.requests_count == 1 - and isinstance(exc, BadHttpMethod) - ): + if self._request_count == 1 and isinstance(exc, BadHttpMethod): # BadHttpMethod is common when a client sends non-HTTP # or encrypted traffic to an HTTP port. This is expected # to happen when connected to the public internet so we log diff --git a/aiohttp/web_server.py b/aiohttp/web_server.py index b6ac25ac1a5..328aca1e405 100644 --- a/aiohttp/web_server.py +++ b/aiohttp/web_server.py @@ -25,6 +25,8 @@ def __init__( self._loop = loop or asyncio.get_running_loop() self._connections: Dict[RequestHandler, asyncio.Transport] = {} self._kwargs = kwargs + # requests_count is the number of requests being processed by the server + # for the lifetime of the server. self.requests_count = 0 self.request_handler = handler self.request_factory = request_factory or self._make_request diff --git a/tests/test_web_server.py b/tests/test_web_server.py index e77df623020..7b9b87a374a 100644 --- a/tests/test_web_server.py +++ b/tests/test_web_server.py @@ -86,6 +86,20 @@ async def handler(request: web.BaseRequest) -> NoReturn: # be probing for TLS/SSL support which is # expected to fail logger.debug.assert_called_with("Error handling request", exc_info=exc) + logger.debug.reset_mock() + + # Now make another connection to the server + # to make sure that the exception is logged + # at debug on a second fresh connection + cli2 = await aiohttp_client(server) + resp = await cli2.get("/path/to") + assert resp.status == 500 + assert resp.headers["Content-Type"].startswith("text/plain") + # BadHttpMethod should be logged as debug + # on the first request since the client may + # be probing for TLS/SSL support which is + # expected to fail + logger.debug.assert_called_with("Error handling request", exc_info=exc) async def test_raw_server_logs_invalid_method_without_loop_debug( From 9df00a132a6ce64e97c455dc26076345e79f68c7 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 21:55:51 +0000 Subject: [PATCH 6/8] [PR #10073/349b7565 backport][3.11] Improve performance of parsing headers (#10083) Co-authored-by: J. Nick Koston --- CHANGES/10073.misc.rst | 1 + aiohttp/_http_parser.pyx | 56 ++++++++++++++++++---------------------- 2 files changed, 26 insertions(+), 31 deletions(-) create mode 100644 CHANGES/10073.misc.rst diff --git a/CHANGES/10073.misc.rst b/CHANGES/10073.misc.rst new file mode 100644 index 00000000000..2a7e3514ea3 --- /dev/null +++ b/CHANGES/10073.misc.rst @@ -0,0 +1 @@ +Improved performance of parsing headers when using the C parser -- by :user:`bdraco`. diff --git a/aiohttp/_http_parser.pyx b/aiohttp/_http_parser.pyx index 988e4247f93..19dc3e63b74 100644 --- a/aiohttp/_http_parser.pyx +++ b/aiohttp/_http_parser.pyx @@ -71,7 +71,7 @@ cdef object CONTENT_ENCODING = hdrs.CONTENT_ENCODING cdef object EMPTY_PAYLOAD = _EMPTY_PAYLOAD cdef object StreamReader = _StreamReader cdef object DeflateBuffer = _DeflateBuffer - +cdef bytes EMPTY_BYTES = b"" cdef inline object extend(object buf, const char* at, size_t length): cdef Py_ssize_t s @@ -277,8 +277,9 @@ cdef class HttpParser: cparser.llhttp_t* _cparser cparser.llhttp_settings_t* _csettings - bytearray _raw_name - bytearray _raw_value + bytes _raw_name + object _name + bytes _raw_value bint _has_value object _protocol @@ -296,7 +297,7 @@ cdef class HttpParser: bytearray _buf str _path str _reason - object _headers + list _headers list _raw_headers bint _upgraded list _messages @@ -350,8 +351,8 @@ cdef class HttpParser: self._payload_exception = payload_exception self._messages = [] - self._raw_name = bytearray() - self._raw_value = bytearray() + self._raw_name = EMPTY_BYTES + self._raw_value = EMPTY_BYTES self._has_value = False self._max_line_size = max_line_size @@ -378,42 +379,35 @@ cdef class HttpParser: self._limit = limit cdef _process_header(self): - if self._raw_name: - raw_name = bytes(self._raw_name) - raw_value = bytes(self._raw_value) - - name = find_header(raw_name) - value = raw_value.decode('utf-8', 'surrogateescape') + cdef str value + if self._raw_name is not EMPTY_BYTES: + name = find_header(self._raw_name) + value = self._raw_value.decode('utf-8', 'surrogateescape') - self._headers.add(name, value) + self._headers.append((name, value)) if name is CONTENT_ENCODING: self._content_encoding = value - PyByteArray_Resize(self._raw_name, 0) - PyByteArray_Resize(self._raw_value, 0) self._has_value = False - self._raw_headers.append((raw_name, raw_value)) + self._raw_headers.append((self._raw_name, self._raw_value)) + self._raw_name = EMPTY_BYTES + self._raw_value = EMPTY_BYTES cdef _on_header_field(self, char* at, size_t length): - cdef Py_ssize_t size - cdef char *buf if self._has_value: self._process_header() - size = PyByteArray_Size(self._raw_name) - PyByteArray_Resize(self._raw_name, size + length) - buf = PyByteArray_AsString(self._raw_name) - memcpy(buf + size, at, length) + if self._raw_name is EMPTY_BYTES: + self._raw_name = at[:length] + else: + self._raw_name += at[:length] cdef _on_header_value(self, char* at, size_t length): - cdef Py_ssize_t size - cdef char *buf - - size = PyByteArray_Size(self._raw_value) - PyByteArray_Resize(self._raw_value, size + length) - buf = PyByteArray_AsString(self._raw_value) - memcpy(buf + size, at, length) + if self._raw_value is EMPTY_BYTES: + self._raw_value = at[:length] + else: + self._raw_value += at[:length] self._has_value = True cdef _on_headers_complete(self): @@ -424,7 +418,7 @@ cdef class HttpParser: chunked = self._cparser.flags & cparser.F_CHUNKED raw_headers = tuple(self._raw_headers) - headers = CIMultiDictProxy(self._headers) + headers = CIMultiDictProxy(CIMultiDict(self._headers)) if self._cparser.type == cparser.HTTP_REQUEST: allowed = upgrade and headers.get("upgrade", "").lower() in ALLOWED_UPGRADES @@ -672,7 +666,7 @@ cdef int cb_on_message_begin(cparser.llhttp_t* parser) except -1: cdef HttpParser pyparser = parser.data pyparser._started = True - pyparser._headers = CIMultiDict() + pyparser._headers = [] pyparser._raw_headers = [] PyByteArray_Resize(pyparser._buf, 0) pyparser._path = None From bf0a9bf40d7e11031aa5b15802bb300de1793823 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 22:00:45 +0000 Subject: [PATCH 7/8] [PR #10073/349b7565 backport][3.12] Improve performance of parsing headers (#10084) Co-authored-by: J. Nick Koston --- CHANGES/10073.misc.rst | 1 + aiohttp/_http_parser.pyx | 56 ++++++++++++++++++---------------------- 2 files changed, 26 insertions(+), 31 deletions(-) create mode 100644 CHANGES/10073.misc.rst diff --git a/CHANGES/10073.misc.rst b/CHANGES/10073.misc.rst new file mode 100644 index 00000000000..2a7e3514ea3 --- /dev/null +++ b/CHANGES/10073.misc.rst @@ -0,0 +1 @@ +Improved performance of parsing headers when using the C parser -- by :user:`bdraco`. diff --git a/aiohttp/_http_parser.pyx b/aiohttp/_http_parser.pyx index 988e4247f93..19dc3e63b74 100644 --- a/aiohttp/_http_parser.pyx +++ b/aiohttp/_http_parser.pyx @@ -71,7 +71,7 @@ cdef object CONTENT_ENCODING = hdrs.CONTENT_ENCODING cdef object EMPTY_PAYLOAD = _EMPTY_PAYLOAD cdef object StreamReader = _StreamReader cdef object DeflateBuffer = _DeflateBuffer - +cdef bytes EMPTY_BYTES = b"" cdef inline object extend(object buf, const char* at, size_t length): cdef Py_ssize_t s @@ -277,8 +277,9 @@ cdef class HttpParser: cparser.llhttp_t* _cparser cparser.llhttp_settings_t* _csettings - bytearray _raw_name - bytearray _raw_value + bytes _raw_name + object _name + bytes _raw_value bint _has_value object _protocol @@ -296,7 +297,7 @@ cdef class HttpParser: bytearray _buf str _path str _reason - object _headers + list _headers list _raw_headers bint _upgraded list _messages @@ -350,8 +351,8 @@ cdef class HttpParser: self._payload_exception = payload_exception self._messages = [] - self._raw_name = bytearray() - self._raw_value = bytearray() + self._raw_name = EMPTY_BYTES + self._raw_value = EMPTY_BYTES self._has_value = False self._max_line_size = max_line_size @@ -378,42 +379,35 @@ cdef class HttpParser: self._limit = limit cdef _process_header(self): - if self._raw_name: - raw_name = bytes(self._raw_name) - raw_value = bytes(self._raw_value) - - name = find_header(raw_name) - value = raw_value.decode('utf-8', 'surrogateescape') + cdef str value + if self._raw_name is not EMPTY_BYTES: + name = find_header(self._raw_name) + value = self._raw_value.decode('utf-8', 'surrogateescape') - self._headers.add(name, value) + self._headers.append((name, value)) if name is CONTENT_ENCODING: self._content_encoding = value - PyByteArray_Resize(self._raw_name, 0) - PyByteArray_Resize(self._raw_value, 0) self._has_value = False - self._raw_headers.append((raw_name, raw_value)) + self._raw_headers.append((self._raw_name, self._raw_value)) + self._raw_name = EMPTY_BYTES + self._raw_value = EMPTY_BYTES cdef _on_header_field(self, char* at, size_t length): - cdef Py_ssize_t size - cdef char *buf if self._has_value: self._process_header() - size = PyByteArray_Size(self._raw_name) - PyByteArray_Resize(self._raw_name, size + length) - buf = PyByteArray_AsString(self._raw_name) - memcpy(buf + size, at, length) + if self._raw_name is EMPTY_BYTES: + self._raw_name = at[:length] + else: + self._raw_name += at[:length] cdef _on_header_value(self, char* at, size_t length): - cdef Py_ssize_t size - cdef char *buf - - size = PyByteArray_Size(self._raw_value) - PyByteArray_Resize(self._raw_value, size + length) - buf = PyByteArray_AsString(self._raw_value) - memcpy(buf + size, at, length) + if self._raw_value is EMPTY_BYTES: + self._raw_value = at[:length] + else: + self._raw_value += at[:length] self._has_value = True cdef _on_headers_complete(self): @@ -424,7 +418,7 @@ cdef class HttpParser: chunked = self._cparser.flags & cparser.F_CHUNKED raw_headers = tuple(self._raw_headers) - headers = CIMultiDictProxy(self._headers) + headers = CIMultiDictProxy(CIMultiDict(self._headers)) if self._cparser.type == cparser.HTTP_REQUEST: allowed = upgrade and headers.get("upgrade", "").lower() in ALLOWED_UPGRADES @@ -672,7 +666,7 @@ cdef int cb_on_message_begin(cparser.llhttp_t* parser) except -1: cdef HttpParser pyparser = parser.data pyparser._started = True - pyparser._headers = CIMultiDict() + pyparser._headers = [] pyparser._raw_headers = [] PyByteArray_Resize(pyparser._buf, 0) pyparser._path = None From 79561a69d4030d245ec5803069d7803c1ef663c6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 1 Dec 2024 16:18:38 -0600 Subject: [PATCH 8/8] Release 3.11.9 (#10085) --- CHANGES.rst | 30 ++++++++++++++++++++++++++++++ CHANGES/10055.bugfix.rst | 1 - CHANGES/10073.misc.rst | 1 - CHANGES/10076.bugfix.rst | 1 - aiohttp/__init__.py | 2 +- 5 files changed, 31 insertions(+), 4 deletions(-) delete mode 120000 CHANGES/10055.bugfix.rst delete mode 100644 CHANGES/10073.misc.rst delete mode 100644 CHANGES/10076.bugfix.rst diff --git a/CHANGES.rst b/CHANGES.rst index 8a003a78c45..8352236c320 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,6 +10,36 @@ .. towncrier release notes start +3.11.9 (2024-12-01) +=================== + +Bug fixes +--------- + +- Fixed invalid method logging unexpected being logged at exception level on subsequent connections -- by :user:`bdraco`. + + + *Related issues and pull requests on GitHub:* + :issue:`10055`, :issue:`10076`. + + + + +Miscellaneous internal changes +------------------------------ + +- Improved performance of parsing headers when using the C parser -- by :user:`bdraco`. + + + *Related issues and pull requests on GitHub:* + :issue:`10073`. + + + + +---- + + 3.11.8 (2024-11-27) =================== diff --git a/CHANGES/10055.bugfix.rst b/CHANGES/10055.bugfix.rst deleted file mode 120000 index b1f45d8b887..00000000000 --- a/CHANGES/10055.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -10076.bugfix.rst \ No newline at end of file diff --git a/CHANGES/10073.misc.rst b/CHANGES/10073.misc.rst deleted file mode 100644 index 2a7e3514ea3..00000000000 --- a/CHANGES/10073.misc.rst +++ /dev/null @@ -1 +0,0 @@ -Improved performance of parsing headers when using the C parser -- by :user:`bdraco`. diff --git a/CHANGES/10076.bugfix.rst b/CHANGES/10076.bugfix.rst deleted file mode 100644 index c577366bbe8..00000000000 --- a/CHANGES/10076.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed invalid method logging unexpected being logged at exception level on subsequent connections -- by :user:`bdraco`. diff --git a/aiohttp/__init__.py b/aiohttp/__init__.py index 7896648923e..5615e5349ae 100644 --- a/aiohttp/__init__.py +++ b/aiohttp/__init__.py @@ -1,4 +1,4 @@ -__version__ = "3.11.9.dev0" +__version__ = "3.11.9" from typing import TYPE_CHECKING, Tuple