- L1 servers now come from L1_SERVERS env var instead of per-user attachment - Added renderers/list.html template showing available servers - Health check shows if servers are online - Elegant error handling for invalid requests (no more raw JSON errors) - Connect button passes auth token to L1 for seamless login Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
94 lines
2.8 KiB
Python
94 lines
2.8 KiB
Python
"""
|
|
Renderer (L1) management routes for L2 server.
|
|
|
|
L1 servers are configured via environment variable L1_SERVERS.
|
|
Users connect to renderers to create and run recipes.
|
|
"""
|
|
|
|
import logging
|
|
from typing import Optional
|
|
|
|
import requests
|
|
from fastapi import APIRouter, Request, Depends, HTTPException
|
|
from fastapi.responses import HTMLResponse, RedirectResponse
|
|
|
|
from artdag_common import render
|
|
from artdag_common.middleware import wants_html, wants_json
|
|
|
|
from ..config import settings
|
|
from ..dependencies import get_templates, require_auth, get_user_from_cookie
|
|
|
|
router = APIRouter()
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def check_renderer_health(url: str, timeout: float = 5.0) -> bool:
|
|
"""Check if a renderer is healthy."""
|
|
try:
|
|
resp = requests.get(f"{url}/", timeout=timeout)
|
|
return resp.status_code == 200
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
@router.get("")
|
|
async def list_renderers(request: Request):
|
|
"""List configured L1 renderers."""
|
|
# Get user if logged in
|
|
username = get_user_from_cookie(request)
|
|
user = None
|
|
if username:
|
|
# Get token for connection links
|
|
token = request.cookies.get("auth_token", "")
|
|
user = {"username": username, "token": token}
|
|
|
|
# Build server list with health status
|
|
servers = []
|
|
for url in settings.l1_servers:
|
|
servers.append({
|
|
"url": url,
|
|
"healthy": check_renderer_health(url),
|
|
})
|
|
|
|
if wants_json(request):
|
|
return {"servers": servers}
|
|
|
|
templates = get_templates(request)
|
|
return render(templates, "renderers/list.html", request,
|
|
servers=servers,
|
|
user=user,
|
|
active_tab="renderers",
|
|
)
|
|
|
|
|
|
@router.get("/{path:path}")
|
|
async def renderer_catchall(path: str, request: Request):
|
|
"""Catch-all for invalid renderer URLs - redirect to list."""
|
|
if wants_json(request):
|
|
raise HTTPException(404, "Not found")
|
|
return RedirectResponse(url="/renderers", status_code=302)
|
|
|
|
|
|
@router.post("")
|
|
@router.post("/{path:path}")
|
|
async def renderer_post_catchall(request: Request, path: str = ""):
|
|
"""
|
|
Catch-all for POST requests.
|
|
|
|
The old API expected JSON POST to attach renderers.
|
|
Now renderers are env-configured, so redirect to the list.
|
|
"""
|
|
if wants_json(request):
|
|
return {
|
|
"error": "Renderers are now configured via environment. See /renderers for available servers.",
|
|
"servers": settings.l1_servers,
|
|
}
|
|
|
|
templates = get_templates(request)
|
|
return render(templates, "renderers/list.html", request,
|
|
servers=[{"url": url, "healthy": check_renderer_health(url)} for url in settings.l1_servers],
|
|
user=get_user_from_cookie(request),
|
|
error="Renderers are configured by the system administrator. Use the Connect button to access a renderer.",
|
|
active_tab="renderers",
|
|
)
|