Home Assistant Unofficial Reference 2024.12.1
cors.py
Go to the documentation of this file.
1 """Provide CORS support for the HTTP component."""
2 
3 from __future__ import annotations
4 
5 from typing import Final, cast
6 
7 from aiohttp.hdrs import ACCEPT, AUTHORIZATION, CONTENT_TYPE, ORIGIN
8 from aiohttp.web import Application
9 from aiohttp.web_urldispatcher import (
10  AbstractResource,
11  AbstractRoute,
12  Resource,
13  ResourceRoute,
14  StaticResource,
15 )
16 import aiohttp_cors
17 
18 from homeassistant.const import HTTP_HEADER_X_REQUESTED_WITH
19 from homeassistant.core import callback
20 from homeassistant.helpers.http import (
21  KEY_ALLOW_ALL_CORS,
22  KEY_ALLOW_CONFIGURED_CORS,
23  AllowCorsType,
24 )
25 
26 ALLOWED_CORS_HEADERS: Final[list[str]] = [
27  ORIGIN,
28  ACCEPT,
29  HTTP_HEADER_X_REQUESTED_WITH,
30  CONTENT_TYPE,
31  AUTHORIZATION,
32 ]
33 VALID_CORS_TYPES: Final = (Resource, ResourceRoute, StaticResource)
34 
35 
36 @callback
37 def setup_cors(app: Application, origins: list[str]) -> None:
38  """Set up CORS."""
39  cors = aiohttp_cors.setup(
40  app,
41  defaults={
42  host: aiohttp_cors.ResourceOptions(
43  allow_headers=ALLOWED_CORS_HEADERS, allow_methods="*"
44  )
45  for host in origins
46  },
47  )
48 
49  cors_added = set()
50 
51  def _allow_cors(
52  route: AbstractRoute | AbstractResource,
53  config: dict[str, aiohttp_cors.ResourceOptions] | None = None,
54  ) -> None:
55  """Allow CORS on a route."""
56  if isinstance(route, AbstractRoute):
57  path = route.resource
58  else:
59  path = route
60 
61  if not isinstance(path, VALID_CORS_TYPES):
62  return
63 
64  path_str = path.canonical
65 
66  if path_str.startswith("/api/hassio_ingress/"):
67  return
68 
69  if path_str in cors_added:
70  return
71 
72  cors.add(route, config)
73  cors_added.add(path_str)
74 
75  app[KEY_ALLOW_ALL_CORS] = lambda route: _allow_cors(
76  route,
77  {
78  "*": aiohttp_cors.ResourceOptions(
79  allow_headers=ALLOWED_CORS_HEADERS, allow_methods="*"
80  )
81  },
82  )
83 
84  if origins:
85  app[KEY_ALLOW_CONFIGURED_CORS] = cast(AllowCorsType, _allow_cors)
86  else:
87  app[KEY_ALLOW_CONFIGURED_CORS] = lambda _: None
None setup_cors(Application app, list[str] origins)
Definition: cors.py:37