|
3 | 3 | from __future__ import annotations
|
4 | 4 |
|
5 | 5 | import asyncio
|
| 6 | +from functools import partial |
6 | 7 | import ipaddress
|
7 | 8 | import logging
|
| 9 | +import os |
| 10 | +from pathlib import Path |
8 | 11 | from typing import Any, Callable, Set, cast
|
9 | 12 | import weakref
|
10 | 13 |
|
|
31 | 34 | from .storage import StorageController
|
32 | 35 | from .vendor_info import VendorInfo
|
33 | 36 |
|
| 37 | +DASHBOARD_DIR = Path(__file__).parent.joinpath("../../dashboard/dist/web/").resolve() |
| 38 | +DASHBOARD_DIR_EXISTS = DASHBOARD_DIR.exists() |
| 39 | + |
34 | 40 |
|
35 | 41 | def mount_websocket(server: MatterServer, path: str) -> None:
|
36 | 42 | """Mount the websocket endpoint."""
|
@@ -106,7 +112,23 @@ async def start(self) -> None:
|
106 | 112 | await self.device_controller.start()
|
107 | 113 | await self.vendor_info.start()
|
108 | 114 | mount_websocket(self, "/ws")
|
109 |
| - self.app.router.add_route("GET", "/", self._handle_info) |
| 115 | + self.app.router.add_route("GET", "/info", self._handle_info) |
| 116 | + |
| 117 | + # Host dashboard if the prebuilt files are detected |
| 118 | + if DASHBOARD_DIR_EXISTS: |
| 119 | + dashboard_dir = str(DASHBOARD_DIR) |
| 120 | + self.logger.debug("Detected dashboard files on %s", dashboard_dir) |
| 121 | + for abs_dir, _, files in os.walk(dashboard_dir): |
| 122 | + rel_dir = abs_dir.replace(dashboard_dir, "") |
| 123 | + for filename in files: |
| 124 | + filepath = os.path.join(abs_dir, filename) |
| 125 | + handler = partial(self._serve_static, filepath) |
| 126 | + if rel_dir == "" and filename == "index.html": |
| 127 | + route_path = "/" |
| 128 | + else: |
| 129 | + route_path = f"{rel_dir}/{filename}" |
| 130 | + self.app.router.add_route("GET", route_path, handler) |
| 131 | + |
110 | 132 | self._runner = web.AppRunner(self.app, access_log=None)
|
111 | 133 | await self._runner.setup()
|
112 | 134 | self._http = MultiHostTCPSite(
|
@@ -233,3 +255,10 @@ async def _handle_info(self, request: web.Request) -> web.Response:
|
233 | 255 | """Handle info endpoint to serve basic server (version) info."""
|
234 | 256 | # pylint: disable=unused-argument
|
235 | 257 | return web.json_response(self.get_info(), dumps=json_dumps)
|
| 258 | + |
| 259 | + async def _serve_static( |
| 260 | + self, file_path: str, _request: web.Request |
| 261 | + ) -> web.FileResponse: |
| 262 | + """Serve file response.""" |
| 263 | + headers = {"Cache-Control": "no-cache"} |
| 264 | + return web.FileResponse(file_path, headers=headers) |
0 commit comments