dev-v0.7.x -> main #22

Merged
alpha-nerd merged 2 commits from dev-v0.7.x into main 2026-04-13 14:00:21 +02:00
2 changed files with 21 additions and 3 deletions

View file

@ -6,7 +6,7 @@ version: 0.7
license: AGPL
"""
# -------------------------------------------------------------
import orjson, time, asyncio, yaml, ollama, openai, os, re, aiohttp, ssl, random, base64, io, enhance, secrets, math
import orjson, time, asyncio, yaml, ollama, openai, os, re, aiohttp, ssl, random, base64, io, enhance, secrets, math, socket
try:
import truststore; truststore.inject_into_ssl()
except ImportError:
@ -373,7 +373,11 @@ async def enforce_router_api_key(request: Request, call_next):
return await call_next(request)
path = request.url.path
if path.startswith("/static") or path in {"/", "/favicon.ico"}:
# Allow static assets (CSS, JS, images, fonts) but NOT HTML pages,
# which would bypass auth by accessing /static/index.html directly.
_STATIC_ASSET_EXTS = {".css", ".js", ".ico", ".png", ".jpg", ".jpeg", ".svg", ".woff", ".woff2", ".ttf", ".map"}
is_static_asset = path.startswith("/static") and Path(path).suffix.lower() in _STATIC_ASSET_EXTS
if is_static_asset or path in {"/", "/favicon.ico"}:
return await call_next(request)
provided_key = _extract_router_api_key(request)
@ -3776,7 +3780,15 @@ async def health_proxy(request: Request):
return JSONResponse(content=response_payload, status_code=http_status)
# -------------------------------------------------------------
# 27. SSE route for usage broadcasts
# 27. Hostname endpoint
# -------------------------------------------------------------
@app.get("/api/hostname")
async def get_hostname():
"""Return the hostname of the machine running the router."""
return JSONResponse(content={"hostname": socket.gethostname()})
# -------------------------------------------------------------
# 28. SSE route for usage broadcasts
# -------------------------------------------------------------
@app.get("/api/usage-stream")
async def usage_stream(request: Request):

View file

@ -344,6 +344,7 @@
</div>
<div class="header-row">
<h1>Router Dashboard</h1>
<span id="hostname" style="color:#777; font-size:0.85em;"></span>
<button id="total-tokens-btn">Stats Total</button>
<span id="aggregation-status" class="loading" style="margin-left:8px;"></span>
</div>
@ -1418,6 +1419,11 @@ function initStatsChart(timeSeriesData, endpointDistribution) {
</script>
<script>
document.addEventListener('DOMContentLoaded', () => {
authedFetch('/api/hostname').then(r => r.json()).then(data => {
const el = document.getElementById('hostname');
if (el && data.hostname) el.textContent = data.hostname;
}).catch(() => {});
const totalBtn = document.getElementById('total-tokens-btn');
if (totalBtn) {
totalBtn.addEventListener('click', async () => {