Konfigurierbares CORS per ZMB_CORS_ORIGINS + dynamische Frontend-URL
- main.py: CORS-Origins aus ZMB_CORS_ORIGINS (kommagetrennt), Default "*" - allow_credentials automatisch aktiv bei konkreten Origins, aus bei "*" - Root-Endpoint liefert Frontend-URL dynamisch via request.base_url - keine hartkodierten IPs mehr im Anwendungscode - Doku in CLAUDE.md und systemd-Unit ergaenzt Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+19
-5
@@ -6,6 +6,7 @@ FastAPI backend for ZFS pool management
|
|||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Set
|
from typing import Set
|
||||||
@@ -35,11 +36,24 @@ app = FastAPI(
|
|||||||
version="1.0.0"
|
version="1.0.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
# CORS middleware (adjust origins for production!)
|
# CORS middleware — configurable via environment variable.
|
||||||
|
# Set ZMB_CORS_ORIGINS to a comma-separated list of allowed origins
|
||||||
|
# (e.g. "https://<host>:8090,http://<host>:3000").
|
||||||
|
# Defaults to "*" for development if unset.
|
||||||
|
_cors_origins_env = os.getenv("ZMB_CORS_ORIGINS", "*").strip()
|
||||||
|
cors_origins = (
|
||||||
|
["*"]
|
||||||
|
if _cors_origins_env == "*"
|
||||||
|
else [origin.strip() for origin in _cors_origins_env.split(",") if origin.strip()]
|
||||||
|
)
|
||||||
|
# allow_credentials cannot be combined with the "*" wildcard per the CORS spec
|
||||||
|
allow_credentials = cors_origins != ["*"]
|
||||||
|
logger.info("CORS allowed origins: %s", cors_origins)
|
||||||
|
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
allow_origins=["*"], # Change to specific origins in production
|
allow_origins=cors_origins,
|
||||||
allow_credentials=True,
|
allow_credentials=allow_credentials,
|
||||||
allow_methods=["*"],
|
allow_methods=["*"],
|
||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
)
|
)
|
||||||
@@ -144,13 +158,13 @@ async def status_check():
|
|||||||
|
|
||||||
# Root endpoint - API info only
|
# Root endpoint - API info only
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
async def root():
|
async def root(request: Request):
|
||||||
"""API info"""
|
"""API info"""
|
||||||
return {
|
return {
|
||||||
"name": "ZMB Webui API",
|
"name": "ZMB Webui API",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"docs": "/docs",
|
"docs": "/docs",
|
||||||
"frontend": "http://192.168.1.179:3000"
|
"frontend": str(request.base_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ WorkingDirectory=/opt/zmb-webui/backend
|
|||||||
Environment="PATH=/opt/zmb-webui/venv/bin"
|
Environment="PATH=/opt/zmb-webui/venv/bin"
|
||||||
Environment="PYTHONUNBUFFERED=1"
|
Environment="PYTHONUNBUFFERED=1"
|
||||||
Environment="PYTHONDONTWRITEBYTECODE=1"
|
Environment="PYTHONDONTWRITEBYTECODE=1"
|
||||||
|
# CORS: comma-separated list of allowed frontend origins.
|
||||||
|
# Leave unset (or "*") for development. Set to specific origins in production,
|
||||||
|
# e.g. Environment="ZMB_CORS_ORIGINS=https://<host>:8090"
|
||||||
|
#Environment="ZMB_CORS_ORIGINS=*"
|
||||||
|
|
||||||
ExecStart=/opt/zmb-webui/venv/bin/python -m uvicorn main:app \
|
ExecStart=/opt/zmb-webui/venv/bin/python -m uvicorn main:app \
|
||||||
--host 0.0.0.0 \
|
--host 0.0.0.0 \
|
||||||
|
|||||||
Reference in New Issue
Block a user