feat: integrate configuration system into FastAPI application
- Use configurable app title, description, and API settings - Add template context injection for all HTML routes - Implement file upload validation with size/extension limits - Add enhanced health check and info endpoints with feature flags - Support conditional API documentation based on settings
This commit is contained in:
@@ -16,22 +16,23 @@ from fastapi.staticfiles import StaticFiles # type: ignore
|
||||
from fastapi.templating import Jinja2Templates # type: ignore
|
||||
from pydantic import BaseModel
|
||||
|
||||
from .core.config import settings
|
||||
from .core.templates import UnitTemplate, template_registry
|
||||
from .core.unit_file import SystemdUnitFile, UnitType, ValidationError, create_unit_file
|
||||
|
||||
# Create FastAPI app
|
||||
app = FastAPI(
|
||||
title="UnitForge",
|
||||
description="Create, validate, and manage systemd unit files",
|
||||
version="1.0.0",
|
||||
docs_url="/api/docs",
|
||||
redoc_url="/api/redoc",
|
||||
title=settings.api_title,
|
||||
description=settings.api_description,
|
||||
version=settings.api_version,
|
||||
docs_url=settings.api_docs_url if settings.api_docs_enabled else None,
|
||||
redoc_url=settings.api_redoc_url if settings.redoc_enabled else None,
|
||||
)
|
||||
|
||||
# Add CORS middleware
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_origins=settings.cors_origins,
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
@@ -39,8 +40,8 @@ app.add_middleware(
|
||||
|
||||
# Setup templates and static files
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
||||
TEMPLATES_DIR = BASE_DIR / "frontend" / "templates"
|
||||
STATIC_DIR = BASE_DIR / "frontend" / "static"
|
||||
TEMPLATES_DIR = BASE_DIR / settings.templates_dir
|
||||
STATIC_DIR = BASE_DIR / settings.static_dir
|
||||
|
||||
templates = Jinja2Templates(directory=str(TEMPLATES_DIR))
|
||||
|
||||
@@ -134,19 +135,25 @@ def template_to_dict(template: UnitTemplate) -> Dict[str, Any]:
|
||||
@app.get("/", response_class=HTMLResponse)
|
||||
async def index(request: Request):
|
||||
"""Serve the main web interface."""
|
||||
return templates.TemplateResponse("index.html", {"request": request})
|
||||
context = {"request": request}
|
||||
context.update(settings.get_template_context())
|
||||
return templates.TemplateResponse("index.html", context)
|
||||
|
||||
|
||||
@app.get("/editor", response_class=HTMLResponse)
|
||||
async def editor(request: Request):
|
||||
"""Serve the unit file editor interface."""
|
||||
return templates.TemplateResponse("editor.html", {"request": request})
|
||||
context = {"request": request}
|
||||
context.update(settings.get_template_context())
|
||||
return templates.TemplateResponse("editor.html", context)
|
||||
|
||||
|
||||
@app.get("/templates", response_class=HTMLResponse)
|
||||
async def templates_page(request: Request):
|
||||
"""Serve the templates browser interface."""
|
||||
return templates.TemplateResponse("templates.html", {"request": request})
|
||||
context = {"request": request}
|
||||
context.update(settings.get_template_context())
|
||||
return templates.TemplateResponse("templates.html", context)
|
||||
|
||||
|
||||
# API Routes
|
||||
@@ -343,6 +350,22 @@ async def download_unit_file(unit_file: UnitFileContent):
|
||||
async def upload_unit_file(file: UploadFile = File(...)):
|
||||
"""Upload and validate a unit file."""
|
||||
try:
|
||||
# Check file size
|
||||
if file.size and file.size > settings.max_upload_size:
|
||||
raise HTTPException(
|
||||
status_code=413,
|
||||
detail=f"File too large. Maximum size is {settings.max_upload_size} bytes"
|
||||
)
|
||||
|
||||
# Check file extension
|
||||
if file.filename:
|
||||
file_ext = Path(file.filename).suffix.lower()
|
||||
if file_ext not in settings.allowed_extensions:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"File type not allowed. Allowed types: {', '.join(settings.allowed_extensions)}"
|
||||
)
|
||||
|
||||
content = await file.read()
|
||||
content_str = content.decode("utf-8")
|
||||
|
||||
@@ -386,11 +409,23 @@ async def upload_unit_file(file: UploadFile = File(...)):
|
||||
async def get_info():
|
||||
"""Get application information."""
|
||||
return {
|
||||
"name": "UnitForge",
|
||||
"version": "1.0.0",
|
||||
"description": "Create, validate, and manage systemd unit files",
|
||||
"name": settings.app_name,
|
||||
"version": settings.app_version,
|
||||
"description": settings.app_description,
|
||||
"environment": settings.environment,
|
||||
"debug": settings.debug,
|
||||
"supported_types": [t.value for t in UnitType],
|
||||
"template_count": len(template_registry.list_templates()),
|
||||
"max_upload_size": settings.max_upload_size,
|
||||
"allowed_extensions": settings.allowed_extensions,
|
||||
"features": {
|
||||
"api_metrics": settings.enable_api_metrics,
|
||||
"template_caching": settings.enable_template_caching,
|
||||
"validation_caching": settings.enable_validation_caching,
|
||||
"api_docs": settings.api_docs_enabled,
|
||||
"swagger_ui": settings.swagger_ui_enabled,
|
||||
"redoc": settings.redoc_enabled,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -398,10 +433,19 @@ async def get_info():
|
||||
@app.get("/health")
|
||||
async def health_check():
|
||||
"""Health check endpoint."""
|
||||
return {"status": "healthy", "service": "unitforge"}
|
||||
if not settings.health_check_enabled:
|
||||
raise HTTPException(status_code=404, detail="Health check disabled")
|
||||
|
||||
return {
|
||||
"status": "healthy",
|
||||
"service": settings.app_name.lower(),
|
||||
"version": settings.app_version,
|
||||
"environment": settings.environment,
|
||||
"timestamp": __import__("datetime").datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn # type: ignore
|
||||
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000) # nosec B104
|
||||
uvicorn.run(app, host=settings.host, port=settings.port) # nosec B104
|
||||
|
||||
Reference in New Issue
Block a user