Compare commits
3 commits
07b80e654f
...
f4b3a09151
| Author | SHA1 | Date | |
|---|---|---|---|
| f4b3a09151 | |||
| 1058f2418b | |||
| 263c66aedd |
2 changed files with 21 additions and 3 deletions
18
router.py
18
router.py
|
|
@ -6,7 +6,7 @@ version: 0.7
|
||||||
license: AGPL
|
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:
|
try:
|
||||||
import truststore; truststore.inject_into_ssl()
|
import truststore; truststore.inject_into_ssl()
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|
@ -373,7 +373,11 @@ async def enforce_router_api_key(request: Request, call_next):
|
||||||
return await call_next(request)
|
return await call_next(request)
|
||||||
|
|
||||||
path = request.url.path
|
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)
|
return await call_next(request)
|
||||||
|
|
||||||
provided_key = _extract_router_api_key(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)
|
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")
|
@app.get("/api/usage-stream")
|
||||||
async def usage_stream(request: Request):
|
async def usage_stream(request: Request):
|
||||||
|
|
|
||||||
|
|
@ -344,6 +344,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="header-row">
|
<div class="header-row">
|
||||||
<h1>Router Dashboard</h1>
|
<h1>Router Dashboard</h1>
|
||||||
|
<span id="hostname" style="color:#777; font-size:0.85em;"></span>
|
||||||
<button id="total-tokens-btn">Stats Total</button>
|
<button id="total-tokens-btn">Stats Total</button>
|
||||||
<span id="aggregation-status" class="loading" style="margin-left:8px;"></span>
|
<span id="aggregation-status" class="loading" style="margin-left:8px;"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1418,6 +1419,11 @@ function initStatsChart(timeSeriesData, endpointDistribution) {
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
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');
|
const totalBtn = document.getElementById('total-tokens-btn');
|
||||||
if (totalBtn) {
|
if (totalBtn) {
|
||||||
totalBtn.addEventListener('click', async () => {
|
totalBtn.addEventListener('click', async () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue