Refactor http CachingStaticResource (#21062)
* Simplify http.CachingStaticResource implementation * Sync up CachingStaticResource._handle() implementation from aiohttp * Ignore pylint duplicate-base warning * Try to disable pylint for http/static.py Caused by https://github.com/PyCQA/astroid/issues/633#issuecomment-463879288 * Remove pylint ignore * Ignore pylint duplicate-base warning
This commit is contained in:
parent
383813bfe6
commit
46efc0eafb
2 changed files with 20 additions and 30 deletions
|
@ -16,13 +16,12 @@ import homeassistant.util as hass_util
|
|||
from homeassistant.util import ssl as ssl_util
|
||||
from homeassistant.util.logging import HideSensitiveDataFilter
|
||||
|
||||
# Import as alias
|
||||
from .auth import setup_auth
|
||||
from .ban import setup_bans
|
||||
from .const import KEY_AUTHENTICATED, KEY_REAL_IP # noqa
|
||||
from .cors import setup_cors
|
||||
from .real_ip import setup_real_ip
|
||||
from .static import CachingFileResponse, CachingStaticResource
|
||||
from .static import CACHE_HEADERS, CachingStaticResource
|
||||
from .view import HomeAssistantView # noqa
|
||||
|
||||
REQUIREMENTS = ['aiohttp_cors==0.7.0']
|
||||
|
@ -272,7 +271,7 @@ class HomeAssistantHTTP:
|
|||
if cache_headers:
|
||||
async def serve_file(request):
|
||||
"""Serve file from disk."""
|
||||
return CachingFileResponse(path)
|
||||
return web.FileResponse(path, headers=CACHE_HEADERS)
|
||||
else:
|
||||
async def serve_file(request):
|
||||
"""Serve file from disk."""
|
||||
|
|
|
@ -1,18 +1,29 @@
|
|||
"""Static file handling for HTTP component."""
|
||||
from pathlib import Path
|
||||
|
||||
from aiohttp import hdrs
|
||||
from aiohttp.web import FileResponse
|
||||
from aiohttp.web_exceptions import HTTPNotFound
|
||||
from aiohttp.web_exceptions import HTTPNotFound, HTTPForbidden
|
||||
from aiohttp.web_urldispatcher import StaticResource
|
||||
from yarl import URL
|
||||
|
||||
CACHE_TIME = 31 * 86400 # = 1 month
|
||||
CACHE_HEADERS = {hdrs.CACHE_CONTROL: "public, max-age={}".format(CACHE_TIME)}
|
||||
|
||||
|
||||
# https://github.com/PyCQA/astroid/issues/633
|
||||
# pylint: disable=duplicate-bases
|
||||
class CachingStaticResource(StaticResource):
|
||||
"""Static Resource handler that will add cache headers."""
|
||||
|
||||
async def _handle(self, request):
|
||||
filename = URL(request.match_info['filename']).path
|
||||
rel_url = request.match_info['filename']
|
||||
try:
|
||||
# PyLint is wrong about resolve not being a member.
|
||||
filename = Path(rel_url)
|
||||
if filename.anchor:
|
||||
# rel_url is an absolute name like
|
||||
# /static/\\machine_name\c$ or /static/D:\path
|
||||
# where the static dir is totally different
|
||||
raise HTTPForbidden()
|
||||
filepath = self._directory.joinpath(filename).resolve()
|
||||
if not self._follow_symlinks:
|
||||
filepath.relative_to(self._directory)
|
||||
|
@ -24,30 +35,10 @@ class CachingStaticResource(StaticResource):
|
|||
request.app.logger.exception(error)
|
||||
raise HTTPNotFound() from error
|
||||
|
||||
# on opening a dir, load its contents if allowed
|
||||
if filepath.is_dir():
|
||||
return await super()._handle(request)
|
||||
if filepath.is_file():
|
||||
return CachingFileResponse(filepath, chunk_size=self._chunk_size)
|
||||
return FileResponse(
|
||||
filepath, chunk_size=self._chunk_size, headers=CACHE_HEADERS)
|
||||
raise HTTPNotFound
|
||||
|
||||
|
||||
# pylint: disable=too-many-ancestors
|
||||
class CachingFileResponse(FileResponse):
|
||||
"""FileSender class that caches output if not in dev mode."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize the hass file sender."""
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
orig_sendfile = self._sendfile
|
||||
|
||||
async def sendfile(request, fobj, count):
|
||||
"""Sendfile that includes a cache header."""
|
||||
cache_time = 31 * 86400 # = 1 month
|
||||
self.headers[hdrs.CACHE_CONTROL] = "public, max-age={}".format(
|
||||
cache_time)
|
||||
|
||||
await orig_sendfile(request, fobj, count)
|
||||
|
||||
# Overwriting like this because __init__ can change implementation.
|
||||
self._sendfile = sendfile
|
||||
|
|
Loading…
Add table
Reference in a new issue