Skip to content

Commit e46c82b

Browse files
committed
Iris needs an icon!
Mostly just trying to make it easier for me to find the tab in chrome
1 parent 75d22e5 commit e46c82b

5 files changed

Lines changed: 55 additions & 23 deletions

File tree

lib/iris/dashboard/favicon.ico

295 KB
Binary file not shown.

lib/iris/dashboard/rsbuild.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export default defineConfig({
2020
templateParameters: {
2121
title: 'Iris Dashboard',
2222
},
23+
favicon: './favicon.ico',
2324
},
2425
server: {
2526
proxy: {

lib/iris/src/iris/cluster/controller/dashboard.py

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,15 @@
3939

4040
from iris.cluster.controller.actor_proxy import PROXY_ROUTE, ActorProxy
4141
from iris.cluster.controller.service import ControllerServiceImpl
42-
from iris.cluster.dashboard_common import html_shell, on_shutdown, static_files_mount
42+
from iris.cluster.dashboard_common import (
43+
_AUTH_POLICY_ATTR,
44+
favicon_route,
45+
html_shell,
46+
on_shutdown,
47+
public,
48+
requires_auth,
49+
static_files_mount,
50+
)
4351
from iris.log_server.client import LogServiceProxy
4452
from iris.log_server.server import LogServiceImpl
4553
from iris.rpc.auth import SESSION_COOKIE, NullAuthInterceptor, TokenVerifier, extract_bearer_token, resolve_auth
@@ -52,25 +60,6 @@
5260

5361
logger = logging.getLogger(__name__)
5462

55-
# ---------------------------------------------------------------------------
56-
# Route auth policy annotations
57-
# ---------------------------------------------------------------------------
58-
59-
_AUTH_POLICY_ATTR = "_auth_policy"
60-
61-
62-
def public(fn: Callable) -> Callable:
63-
"""Mark a route handler as publicly accessible (no auth required)."""
64-
setattr(fn, _AUTH_POLICY_ATTR, "public")
65-
return fn
66-
67-
68-
def requires_auth(fn: Callable) -> Callable:
69-
"""Mark a route handler as requiring authentication via session cookie or Bearer token."""
70-
setattr(fn, _AUTH_POLICY_ATTR, "requires_auth")
71-
return fn
72-
73-
7463
def _extract_token_from_scope(scope: Scope) -> str | None:
7564
"""Extract auth token from ASGI scope (cookie or Authorization header)."""
7665
headers: dict[str, str] = {k.decode(): v.decode() for k, v in scope.get("headers", [])}
@@ -318,6 +307,7 @@ async def _proxy_actor_rpc(request: Request) -> Response:
318307

319308
routes = [
320309
Route("/", self._dashboard),
310+
favicon_route(),
321311
Route("/auth/session_bootstrap", self._session_bootstrap),
322312
Route("/auth/config", self._auth_config),
323313
Route("/auth/session", self._auth_session, methods=["POST"]),
@@ -484,6 +474,7 @@ def app(self) -> Starlette:
484474
def _create_app(self) -> Starlette:
485475
routes = [
486476
Route("/", self._dashboard),
477+
favicon_route(),
487478
Route("/job/{job_id:path}", self._job_detail_page),
488479
Route("/worker/{worker_id:path}", self._worker_detail_page),
489480
Route("/bundles/{bundle_id:str}.zip", self._proxy_bundle),

lib/iris/src/iris/cluster/dashboard_common.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,32 @@
1515
from typing import Any
1616

1717
from starlette.applications import Starlette
18-
from starlette.responses import PlainTextResponse
19-
from starlette.routing import Mount
18+
from starlette.requests import Request
19+
from starlette.responses import PlainTextResponse, Response
20+
from starlette.routing import Mount, Route
2021
from starlette.staticfiles import StaticFiles
2122
from starlette.types import ASGIApp, Receive, Scope, Send
2223

2324
logger = logging.getLogger(__name__)
2425

26+
# ---------------------------------------------------------------------------
27+
# Route auth policy annotations
28+
# ---------------------------------------------------------------------------
29+
30+
_AUTH_POLICY_ATTR = "_auth_policy"
31+
32+
33+
def public(fn: Callable) -> Callable:
34+
"""Mark a route handler as publicly accessible (no auth required)."""
35+
setattr(fn, _AUTH_POLICY_ATTR, "public")
36+
return fn
37+
38+
39+
def requires_auth(fn: Callable) -> Callable:
40+
"""Mark a route handler as requiring authentication via session cookie or Bearer token."""
41+
setattr(fn, _AUTH_POLICY_ATTR, "requires_auth")
42+
return fn
43+
2544

2645
def on_shutdown(
2746
*callbacks: Callable[[], Awaitable[None]],
@@ -115,6 +134,26 @@ def static_files_mount() -> Mount:
115134
return Mount("/static", app=_LazyStaticFiles(), name="static")
116135

117136

137+
@public
138+
def _favicon(_request: Request) -> Response:
139+
dist = _vue_dist_dir()
140+
if dist is None:
141+
return Response(status_code=404)
142+
favicon_path = dist / "favicon.ico"
143+
if not favicon_path.exists():
144+
return Response(status_code=404)
145+
return Response(
146+
content=favicon_path.read_bytes(),
147+
media_type="image/x-icon",
148+
headers={"cache-control": f"public, max-age={STATIC_MAX_AGE_SECONDS}"},
149+
)
150+
151+
152+
def favicon_route() -> Route:
153+
"""Route for serving favicon.ico from the Vue dashboard dist root."""
154+
return Route("/favicon.ico", _favicon)
155+
156+
118157
_NOT_BUILT_HTML = """\
119158
<!doctype html>
120159
<html><body>

lib/iris/src/iris/cluster/worker/dashboard.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from starlette.routing import Mount, Route
1111

1212
from iris.cluster.worker.service import WorkerServiceImpl
13-
from iris.cluster.dashboard_common import html_shell, static_files_mount
13+
from iris.cluster.dashboard_common import favicon_route, html_shell, static_files_mount
1414
from iris.rpc.worker_connect import WorkerServiceWSGIApplication
1515

1616

@@ -43,6 +43,7 @@ def _create_app(self) -> Starlette:
4343
routes = [
4444
Route("/health", self._health),
4545
Route("/", self._dashboard),
46+
favicon_route(),
4647
Route("/task/{task_id:path}", self._task_detail_page),
4748
Route("/status", self._status_page),
4849
static_files_mount(),

0 commit comments

Comments
 (0)