Ensure large payloads are compressed in the executor with aiohttp 3.9.0 (#103592)

This commit is contained in:
J. Nick Koston 2023-11-07 12:37:54 -06:00 committed by GitHub
parent d3ed8a6b8b
commit 0d63e2f9b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 23 additions and 4 deletions

View File

@ -41,6 +41,7 @@ from homeassistant.exceptions import (
Unauthorized, Unauthorized,
) )
from homeassistant.helpers import config_validation as cv, template from homeassistant.helpers import config_validation as cv, template
from homeassistant.helpers.aiohttp_compat import enable_compression
from homeassistant.helpers.event import EventStateChangedData from homeassistant.helpers.event import EventStateChangedData
from homeassistant.helpers.json import json_dumps from homeassistant.helpers.json import json_dumps
from homeassistant.helpers.service import async_get_all_descriptions from homeassistant.helpers.service import async_get_all_descriptions
@ -219,7 +220,7 @@ class APIStatesView(HomeAssistantView):
response = web.Response( response = web.Response(
body=f'[{",".join(states)}]', content_type=CONTENT_TYPE_JSON body=f'[{",".join(states)}]', content_type=CONTENT_TYPE_JSON
) )
response.enable_compression() enable_compression(response)
return response return response

View File

@ -17,6 +17,7 @@ from yarl import URL
from homeassistant.components.http import HomeAssistantView from homeassistant.components.http import HomeAssistantView
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.aiohttp_compat import enable_compression
from homeassistant.helpers.typing import UNDEFINED from homeassistant.helpers.typing import UNDEFINED
from .const import X_HASS_SOURCE, X_INGRESS_PATH from .const import X_HASS_SOURCE, X_INGRESS_PATH
@ -191,7 +192,7 @@ class HassIOIngress(HomeAssistantView):
if content_length_int > MIN_COMPRESSED_SIZE and should_compress( if content_length_int > MIN_COMPRESSED_SIZE and should_compress(
content_type or simple_response.content_type content_type or simple_response.content_type
): ):
simple_response.enable_compression() enable_compression(simple_response)
await simple_response.prepare(request) await simple_response.prepare(request)
return simple_response return simple_response

View File

@ -20,6 +20,7 @@ import voluptuous as vol
from homeassistant import exceptions from homeassistant import exceptions
from homeassistant.const import CONTENT_TYPE_JSON from homeassistant.const import CONTENT_TYPE_JSON
from homeassistant.core import Context, HomeAssistant, is_callback from homeassistant.core import Context, HomeAssistant, is_callback
from homeassistant.helpers.aiohttp_compat import enable_compression
from homeassistant.helpers.json import ( from homeassistant.helpers.json import (
find_paths_unserializable_data, find_paths_unserializable_data,
json_bytes, json_bytes,
@ -72,7 +73,7 @@ class HomeAssistantView:
status=int(status_code), status=int(status_code),
headers=headers, headers=headers,
) )
response.enable_compression() enable_compression(response)
return response return response
def json_message( def json_message(

View File

@ -1,7 +1,7 @@
"""Helper to restore old aiohttp behavior.""" """Helper to restore old aiohttp behavior."""
from __future__ import annotations from __future__ import annotations
from aiohttp import web_protocol, web_server from aiohttp import web, web_protocol, web_server
class CancelOnDisconnectRequestHandler(web_protocol.RequestHandler): class CancelOnDisconnectRequestHandler(web_protocol.RequestHandler):
@ -23,3 +23,19 @@ def restore_original_aiohttp_cancel_behavior() -> None:
""" """
web_protocol.RequestHandler = CancelOnDisconnectRequestHandler # type: ignore[misc] web_protocol.RequestHandler = CancelOnDisconnectRequestHandler # type: ignore[misc]
web_server.RequestHandler = CancelOnDisconnectRequestHandler # type: ignore[misc] web_server.RequestHandler = CancelOnDisconnectRequestHandler # type: ignore[misc]
def enable_compression(response: web.Response) -> None:
"""Enable compression on the response."""
#
# Set _zlib_executor_size in the constructor once support for
# aiohttp < 3.9.0 is dropped
#
# We want large zlib payloads to be compressed in the executor
# to avoid blocking the event loop.
#
# 32KiB was chosen based on testing in production.
# aiohttp will generate a warning for payloads larger than 1MiB
#
response._zlib_executor_size = 32768 # pylint: disable=protected-access
response.enable_compression()