controller: browser_overlays + extra_http_headers — auth для protected dashboards

Use case: Grafana service account token, basic auth, custom UA. Headers
устанавливаются через page.set_extra_http_headers перед первым goto.

Пример:
  dashboards:
    - id: grafana_gpu
      url: https://chat2.goldix.org/grafana/d/UID/dash
      extra_http_headers:
        Authorization: "Bearer glsa_xxxxxxxxxxxx"

Без этого Grafana с auth gate показывает empty login page (см. test
2026-05-22 ночью: page.screenshot вернул только footer "Documentation/
Support/Community" — content area empty потому что unauthorized).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
gx
2026-05-21 23:22:24 +01:00
parent 19ddaf2dde
commit bd9dcd2441
@@ -69,6 +69,10 @@ class DashboardCfg(BaseModel):
)
page_timeout_ms: int = Field(default=10000, ge=1000, le=60000,
description="Max time to wait for page load")
extra_http_headers: dict[str, str] = Field(default_factory=dict,
description="HTTP headers для каждого request — auth tokens, custom UA. "
"Пример Grafana service account: "
'{"Authorization": "Bearer glsa_xxxxxxxx"}')
opacity: float = 1.0
z_order: int = 28
@@ -109,12 +113,15 @@ class BrowserRenderer:
self.icon_dir.mkdir(parents=True, exist_ok=True)
self._playwright = await async_playwright().start()
# Transparent background через `--default-background-color=00000000`
# (требует hex с alpha=00 для full transparency).
# Full chromium (не headless-shell) — нужен для `--default-background-color`
# transparency support. headless-shell incompatible с remote debugging при
# этом флаге. channel="chromium" → use full browser binary (~170MB,
# установлен через `playwright install chromium`).
self._browser = await self._playwright.chromium.launch(
channel="chromium",
headless=True,
args=[
"--default-background-color=00000000",
"--default-background-color=00000000", # hex alpha=00 = full transparent
"--no-sandbox", # требуется в docker root context
"--disable-dev-shm-usage", # /dev/shm в Docker обычно мал
"--disable-gpu", # headless без GPU OK для PIL
@@ -128,6 +135,8 @@ class BrowserRenderer:
page = await self._browser.new_page(
viewport={"width": vw, "height": vh},
)
if cfg.extra_http_headers:
await page.set_extra_http_headers(cfg.extra_http_headers)
# background_color в new_context не работает для transparent — used CLI arg
await page.goto(cfg.url, wait_until=cfg.wait_until,
timeout=cfg.page_timeout_ms)