From 408e977b17f2f9fa25c9f79ab5a173c56d674b5a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 6 Nov 2023 13:48:47 -0600 Subject: [PATCH] Try to avoid re-parsing the content-type in hassio ingress if possible (#103477) Co-authored-by: Stefan Agner Co-authored-by: Franck Nijhof --- homeassistant/components/hassio/ingress.py | 9 ++++++-- tests/components/hassio/test_ingress.py | 24 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/hassio/ingress.py b/homeassistant/components/hassio/ingress.py index b8c5873b967..345c14163f5 100644 --- a/homeassistant/components/hassio/ingress.py +++ b/homeassistant/components/hassio/ingress.py @@ -169,6 +169,11 @@ class HassIOIngress(HomeAssistantView): headers = _response_header(result) content_length_int = 0 content_length = result.headers.get(hdrs.CONTENT_LENGTH, UNDEFINED) + # Avoid parsing content_type in simple cases for better performance + if maybe_content_type := result.headers.get(hdrs.CONTENT_TYPE): + content_type = (maybe_content_type.partition(";"))[0].strip() + else: + content_type = result.content_type # Simple request if result.status in (204, 304) or ( content_length is not UNDEFINED @@ -180,11 +185,11 @@ class HassIOIngress(HomeAssistantView): simple_response = web.Response( headers=headers, status=result.status, - content_type=result.content_type, + content_type=content_type, body=body, ) if content_length_int > MIN_COMPRESSED_SIZE and should_compress( - simple_response.content_type + content_type or simple_response.content_type ): simple_response.enable_compression() await simple_response.prepare(request) diff --git a/tests/components/hassio/test_ingress.py b/tests/components/hassio/test_ingress.py index 3eda10b1514..c8255ac0496 100644 --- a/tests/components/hassio/test_ingress.py +++ b/tests/components/hassio/test_ingress.py @@ -427,6 +427,30 @@ async def test_ingress_request_not_compressed( assert "Content-Encoding" not in resp.headers +async def test_ingress_request_with_charset_in_content_type( + hassio_noauth_client, aioclient_mock: AiohttpClientMocker +) -> None: + """Test ingress passes content type.""" + body = b"this_is_long_enough_to_be_compressed" * 100 + aioclient_mock.get( + "http://127.0.0.1/ingress/core/x.any", + data=body, + headers={ + "Content-Length": len(body), + "Content-Type": "text/html; charset=utf-8", + }, + ) + + resp = await hassio_noauth_client.get( + "/api/hassio_ingress/core/x.any", + headers={"X-Test-Header": "beer", "Accept-Encoding": "gzip, deflate"}, + ) + + # Check we got right response + assert resp.status == HTTPStatus.OK + assert resp.headers["Content-Type"] == "text/html" + + @pytest.mark.parametrize( "content_type", [