Cache the mime type of static files (#103281)

This commit is contained in:
J. Nick Koston 2023-11-03 12:37:29 -05:00 committed by GitHub
parent 4778c55d2b
commit 062b510ec0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,7 +1,8 @@
"""Static file handling for HTTP component."""
from __future__ import annotations
from collections.abc import Mapping
from collections.abc import Mapping, MutableMapping
import mimetypes
from pathlib import Path
from typing import Final
@ -16,10 +17,11 @@ from homeassistant.core import HomeAssistant
from .const import KEY_HASS
CACHE_TIME: Final = 31 * 86400 # = 1 month
CACHE_HEADERS: Final[Mapping[str, str]] = {
hdrs.CACHE_CONTROL: f"public, max-age={CACHE_TIME}"
}
PATH_CACHE = LRU(512)
CACHE_HEADER = f"public, max-age={CACHE_TIME}"
CACHE_HEADERS: Mapping[str, str] = {hdrs.CACHE_CONTROL: CACHE_HEADER}
PATH_CACHE: MutableMapping[
tuple[str, Path, bool], tuple[Path | None, str | None]
] = LRU(512)
def _get_file_path(rel_url: str, directory: Path, follow_symlinks: bool) -> Path | None:
@ -48,7 +50,7 @@ class CachingStaticResource(StaticResource):
"""Return requested file from disk as a FileResponse."""
rel_url = request.match_info["filename"]
key = (rel_url, self._directory, self._follow_symlinks)
if (filepath := PATH_CACHE.get(key)) is None:
if (filepath_content_type := PATH_CACHE.get(key)) is None:
hass: HomeAssistant = request.app[KEY_HASS]
try:
filepath = await hass.async_add_executor_job(_get_file_path, *key)
@ -62,13 +64,24 @@ class CachingStaticResource(StaticResource):
# perm error or other kind!
request.app.logger.exception(error)
raise HTTPNotFound() from error
PATH_CACHE[key] = filepath
if filepath:
content_type: str | None = None
if filepath is not None:
content_type = (mimetypes.guess_type(rel_url))[
0
] or "application/octet-stream"
PATH_CACHE[key] = (filepath, content_type)
else:
filepath, content_type = filepath_content_type
if filepath and content_type:
return FileResponse(
filepath,
chunk_size=self._chunk_size,
headers=CACHE_HEADERS,
headers={
hdrs.CACHE_CONTROL: CACHE_HEADER,
hdrs.CONTENT_TYPE: content_type,
},
)
return await super()._handle(request)