core/homeassistant/components/http/web_runner.py

72 lines
2.2 KiB
Python
Raw Normal View History

"""HomeAssistant specific aiohttp Site."""
2021-03-18 08:25:40 +00:00
from __future__ import annotations
import asyncio
from ssl import SSLContext
from aiohttp import web
from yarl import URL
class HomeAssistantTCPSite(web.BaseSite):
"""HomeAssistant specific aiohttp Site.
Vanilla TCPSite accepts only str as host. However, the underlying asyncio's
create_server() implementation does take a list of strings to bind to multiple
host IP's. To support multiple server_host entries (e.g. to enable dual-stack
explicitly), we would like to pass an array of strings. Bring our own
implementation inspired by TCPSite.
Custom TCPSite can be dropped when https://github.com/aio-libs/aiohttp/pull/4894
is merged.
"""
__slots__ = ("_host", "_port", "_reuse_address", "_reuse_port", "_hosturl")
def __init__(
self,
2021-03-22 12:29:39 +00:00
runner: web.BaseRunner,
2021-03-18 08:25:40 +00:00
host: None | str | list[str],
port: int,
*,
Shutdown asyncio http server within 10 seconds (#45033) If there are open requests, the http server waits up to 60 seconds. However, some requests (such as the Reboot button) seems to keep a connection open and needlessly slow down the reboot process: ``` Jan 11 00:52:54 homeassistant eb034fca9c7d[404]: 2021-01-11 00:52:54 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event homeassistant_stop[L]> Jan 11 00:52:54 homeassistant eb034fca9c7d[404]: 2021-01-11 00:52:54 DEBUG (MainThread) [homeassistant.helpers.restore_state] Dumping states 111 Jan 11 00:52:54 homeassistant eb034fca9c7d[404]: 2021-01-11 00:52:54 DEBUG (MainThread) [homeassistant.helpers.restore_state] Dumping states Jan 11 00:52:54 homeassistant eb034fca9c7d[404]: 2021-01-11 00:52:54 INFO (MainThread) [homeassistant.components.websocket_api.http.connection] [281473359593728] Connection closed by client Jan 11 00:52:56 homeassistant eb034fca9c7d[404]: 2021-01-11 00:52:56 DEBUG (MainThread) [homeassistant.components.websocket_api.http.connection] [281473359593728] Disconnected Jan 11 00:53:54 homeassistant eb034fca9c7d[404]: 2021-01-11 00:53:54 DEBUG (MainThread) [homeassistant.core] Waited 60 seconds for task: <Task pending name='Task-585' coro=<async_setup.<locals>.stop_server() running at /usr/src/homeassistant/homeassistant/components/http/__init__.py:228> wait_for=<_GatheringFuture pending cb=[<TaskWakeupMethWrapper object at 0xffff9f112f70>()]> cb=[_wait.<locals>._on_completion() at /usr/local/lib/python3.8/asyncio/tasks.py:518]> ... ```
2021-01-11 08:36:14 +00:00
shutdown_timeout: float = 10.0,
2021-03-18 08:25:40 +00:00
ssl_context: SSLContext | None = None,
backlog: int = 128,
2021-03-18 08:25:40 +00:00
reuse_address: bool | None = None,
reuse_port: bool | None = None,
) -> None:
"""Initialize HomeAssistantTCPSite."""
super().__init__(
runner,
shutdown_timeout=shutdown_timeout,
ssl_context=ssl_context,
backlog=backlog,
)
self._host = host
self._port = port
self._reuse_address = reuse_address
self._reuse_port = reuse_port
@property
def name(self) -> str:
"""Return server URL."""
scheme = "https" if self._ssl_context else "http"
host = self._host[0] if isinstance(self._host, list) else "0.0.0.0"
return str(URL.build(scheme=scheme, host=host, port=self._port))
async def start(self) -> None:
"""Start server."""
await super().start()
loop = asyncio.get_running_loop()
server = self._runner.server
assert server is not None
self._server = await loop.create_server(
server,
self._host,
self._port,
ssl=self._ssl_context,
backlog=self._backlog,
reuse_address=self._reuse_address,
reuse_port=self._reuse_port,
)