diff --git a/homeassistant/components/hassio/http.py b/homeassistant/components/hassio/http.py index 6d60fd0a435..2b34a48149b 100644 --- a/homeassistant/components/hassio/http.py +++ b/homeassistant/components/hassio/http.py @@ -42,15 +42,15 @@ NO_TIMEOUT = re.compile( r"|backups/.+/full" r"|backups/.+/partial" r"|backups/[^/]+/(?:upload|download)" - r"|audio/logs/follow" - r"|cli/logs/follow" - r"|core/logs/follow" - r"|dns/logs/follow" - r"|host/logs/follow" - r"|multicast/logs/follow" - r"|observer/logs/follow" - r"|supervisor/logs/follow" - r"|addons/[^/]+/logs/follow" + r"|audio/logs/(follow|boots/-?\d+(/follow)?)" + r"|cli/logs/(follow|boots/-?\d+(/follow)?)" + r"|core/logs/(follow|boots/-?\d+(/follow)?)" + r"|dns/logs/(follow|boots/-?\d+(/follow)?)" + r"|host/logs/(follow|boots/-?\d+(/follow)?)" + r"|multicast/logs/(follow|boots/-?\d+(/follow)?)" + r"|observer/logs/(follow|boots/-?\d+(/follow)?)" + r"|supervisor/logs/(follow|boots/-?\d+(/follow)?)" + r"|addons/[^/]+/logs/(follow|boots/-?\d+(/follow)?)" r")$" ) @@ -68,24 +68,16 @@ PATHS_ADMIN = re.compile( r"^(?:" r"|backups/[a-f0-9]{8}(/info|/download|/restore/full|/restore/partial)?" r"|backups/new/upload" - r"|audio/logs" - r"|audio/logs/follow" - r"|cli/logs" - r"|cli/logs/follow" - r"|core/logs" - r"|core/logs/follow" - r"|dns/logs" - r"|dns/logs/follow" - r"|host/logs" - r"|host/logs/follow" - r"|multicast/logs" - r"|multicast/logs/follow" - r"|observer/logs" - r"|observer/logs/follow" - r"|supervisor/logs" - r"|supervisor/logs/follow" - r"|addons/[^/]+/(changelog|documentation|logs)" - r"|addons/[^/]+/logs/follow" + r"|audio/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|cli/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|core/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|dns/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|host/logs(/follow|/boots(/-?\d+(/follow)?)?)?" + r"|multicast/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|observer/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|supervisor/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|addons/[^/]+/(changelog|documentation)" + r"|addons/[^/]+/logs(/follow|/boots/-?\d+(/follow)?)?" r")$" ) @@ -106,38 +98,29 @@ NO_STORE = re.compile( # Follow logs should not be compressed, to be able to get streamed by frontend NO_COMPRESS = re.compile( r"^(?:" - r"|audio/logs/follow" - r"|cli/logs/follow" - r"|core/logs/follow" - r"|dns/logs/follow" - r"|host/logs/follow" - r"|multicast/logs/follow" - r"|observer/logs/follow" - r"|supervisor/logs/follow" - r"|addons/[^/]+/logs/follow" + r"|audio/logs/(follow|boots/-?\d+(/follow)?)" + r"|cli/logs/(follow|boots/-?\d+(/follow)?)" + r"|core/logs/(follow|boots/-?\d+(/follow)?)" + r"|dns/logs/(follow|boots/-?\d+(/follow)?)" + r"|host/logs/(follow|boots/-?\d+(/follow)?)" + r"|multicast/logs/(follow|boots/-?\d+(/follow)?)" + r"|observer/logs/(follow|boots/-?\d+(/follow)?)" + r"|supervisor/logs/(follow|boots/-?\d+(/follow)?)" + r"|addons/[^/]+/logs/(follow|boots/-?\d+(/follow)?)" r")$" ) PATHS_LOGS = re.compile( r"^(?:" - r"|audio/logs" - r"|audio/logs/follow" - r"|cli/logs" - r"|cli/logs/follow" - r"|core/logs" - r"|core/logs/follow" - r"|dns/logs" - r"|dns/logs/follow" - r"|host/logs" - r"|host/logs/follow" - r"|multicast/logs" - r"|multicast/logs/follow" - r"|observer/logs" - r"|observer/logs/follow" - r"|supervisor/logs" - r"|supervisor/logs/follow" - r"|addons/[^/]+/logs" - r"|addons/[^/]+/logs/follow" + r"|audio/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|cli/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|core/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|dns/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|host/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|multicast/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|observer/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|supervisor/logs(/follow|/boots/-?\d+(/follow)?)?" + r"|addons/[^/]+/logs(/follow|/boots/-?\d+(/follow)?)?" r")$" ) # fmt: on diff --git a/tests/components/hassio/test_http.py b/tests/components/hassio/test_http.py index 5d316da1a12..8ed59bc78d1 100644 --- a/tests/components/hassio/test_http.py +++ b/tests/components/hassio/test_http.py @@ -527,7 +527,10 @@ async def test_forward_range_header_for_logs( ) -> None: """Test that we forward the Range header for logs.""" aioclient_mock.get("http://127.0.0.1/host/logs") + aioclient_mock.get("http://127.0.0.1/host/logs/boots/-1") + aioclient_mock.get("http://127.0.0.1/host/logs/boots/-2/follow?lines=100") aioclient_mock.get("http://127.0.0.1/addons/123abc_esphome/logs") + aioclient_mock.get("http://127.0.0.1/addons/123abc_esphome/logs/follow") aioclient_mock.get("http://127.0.0.1/backups/1234abcd/download") test_range = ":-100:50" @@ -535,24 +538,34 @@ async def test_forward_range_header_for_logs( host_resp = await hassio_client.get( "/api/hassio/host/logs", headers={"Range": test_range} ) + host_resp2 = await hassio_client.get( + "/api/hassio/host/logs/boots/-1", headers={"Range": test_range} + ) + host_resp3 = await hassio_client.get( + "/api/hassio/host/logs/boots/-2/follow?lines=100", headers={"Range": test_range} + ) addon_resp = await hassio_client.get( "/api/hassio/addons/123abc_esphome/logs", headers={"Range": test_range} ) + addon_resp2 = await hassio_client.get( + "/api/hassio/addons/123abc_esphome/logs/follow", headers={"Range": test_range} + ) backup_resp = await hassio_client.get( "/api/hassio/backups/1234abcd/download", headers={"Range": test_range} ) assert host_resp.status == HTTPStatus.OK + assert host_resp2.status == HTTPStatus.OK + assert host_resp3.status == HTTPStatus.OK assert addon_resp.status == HTTPStatus.OK + assert addon_resp2.status == HTTPStatus.OK assert backup_resp.status == HTTPStatus.OK - assert len(aioclient_mock.mock_calls) == 3 + assert len(aioclient_mock.mock_calls) == 6 - req_headers1 = aioclient_mock.mock_calls[0][-1] - assert req_headers1.get("Range") == test_range - - req_headers2 = aioclient_mock.mock_calls[1][-1] - assert req_headers2.get("Range") == test_range - - req_headers3 = aioclient_mock.mock_calls[2][-1] - assert req_headers3.get("Range") is None + assert aioclient_mock.mock_calls[0][-1].get("Range") == test_range + assert aioclient_mock.mock_calls[1][-1].get("Range") == test_range + assert aioclient_mock.mock_calls[2][-1].get("Range") == test_range + assert aioclient_mock.mock_calls[3][-1].get("Range") == test_range + assert aioclient_mock.mock_calls[4][-1].get("Range") == test_range + assert aioclient_mock.mock_calls[5][-1].get("Range") is None