|
# retoor <retoor@molodetz.nl>
|
|
|
|
import logging
|
|
|
|
from fastapi import Request
|
|
from fastapi.responses import JSONResponse, RedirectResponse
|
|
from pydantic import BaseModel
|
|
|
|
from devplacepy.schemas import ActionResult
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def wants_json(request: Request) -> bool:
|
|
content_type = request.headers.get("content-type", "")
|
|
if content_type.startswith("application/json"):
|
|
return True
|
|
accept = request.headers.get("accept", "")
|
|
return "application/json" in accept and "text/html" not in accept
|
|
|
|
|
|
def respond(request: Request, template: str, context: dict, *, model: type[BaseModel]):
|
|
if wants_json(request):
|
|
try:
|
|
payload = model.model_validate(context).model_dump(mode="json")
|
|
except Exception as exc:
|
|
logger.warning("JSON serialization failed for %s: %s", template, exc)
|
|
return json_error(500, "Could not serialize response")
|
|
return JSONResponse(payload)
|
|
from devplacepy.templating import templates
|
|
|
|
return templates.TemplateResponse(request, template, context)
|
|
|
|
|
|
def action_result(
|
|
request: Request, redirect_url: str, *, data: dict | None = None, status_code: int = 302
|
|
) -> JSONResponse | RedirectResponse:
|
|
if wants_json(request):
|
|
return JSONResponse(
|
|
ActionResult(ok=True, redirect=redirect_url, data=data).model_dump(
|
|
mode="json"
|
|
)
|
|
)
|
|
return RedirectResponse(url=redirect_url, status_code=status_code)
|
|
|
|
|
|
def json_error(status_code: int, message: str, **extra) -> JSONResponse:
|
|
return JSONResponse(
|
|
{"error": {"status": status_code, "message": message, **extra}},
|
|
status_code=status_code,
|
|
)
|