core/homeassistant/components/http/cors.py

86 lines
2.2 KiB
Python
Raw Normal View History

2018-08-19 20:29:08 +00:00
"""Provide CORS support for the HTTP component."""
from __future__ import annotations
from typing import Final
2019-12-05 12:42:09 +00:00
from aiohttp.hdrs import ACCEPT, AUTHORIZATION, CONTENT_TYPE, ORIGIN
from aiohttp.web import Application
from aiohttp.web_urldispatcher import (
AbstractResource,
AbstractRoute,
Resource,
ResourceRoute,
StaticResource,
)
from homeassistant.const import HTTP_HEADER_X_REQUESTED_WITH
from homeassistant.core import callback
ALLOWED_CORS_HEADERS: Final[list[str]] = [
2019-07-31 19:25:30 +00:00
ORIGIN,
ACCEPT,
HTTP_HEADER_X_REQUESTED_WITH,
CONTENT_TYPE,
AUTHORIZATION,
]
VALID_CORS_TYPES: Final = (Resource, ResourceRoute, StaticResource)
@callback
def setup_cors(app: Application, origins: list[str]) -> None:
2018-08-19 20:29:08 +00:00
"""Set up CORS."""
# This import should remain here. That way the HTTP integration can always
# be imported by other integrations without it's requirements being installed.
2019-12-05 12:42:09 +00:00
# pylint: disable=import-outside-toplevel
import aiohttp_cors
2019-07-31 19:25:30 +00:00
cors = aiohttp_cors.setup(
app,
defaults={
host: aiohttp_cors.ResourceOptions(
allow_headers=ALLOWED_CORS_HEADERS, allow_methods="*"
)
for host in origins
},
)
cors_added = set()
def _allow_cors(
route: AbstractRoute | AbstractResource,
config: dict[str, aiohttp_cors.ResourceOptions] | None = None,
) -> None:
2018-08-19 20:29:08 +00:00
"""Allow CORS on a route."""
if isinstance(route, AbstractRoute):
path = route.resource
else:
path = route
2019-06-03 18:43:13 +00:00
if not isinstance(path, VALID_CORS_TYPES):
return
path_str = path.canonical
if path_str.startswith("/api/hassio_ingress/"):
return
if path_str in cors_added:
return
cors.add(route, config)
cors_added.add(path_str)
app["allow_all_cors"] = lambda route: _allow_cors(
2019-07-31 19:25:30 +00:00
route,
{
"*": aiohttp_cors.ResourceOptions(
allow_headers=ALLOWED_CORS_HEADERS, allow_methods="*"
)
},
)
if origins:
app["allow_configured_cors"] = _allow_cors
else:
app["allow_configured_cors"] = lambda _: None