"""POST /assets — extract image/video/audio/svg-icon/font assets from a URL.""" import logging import uuid from fastapi import APIRouter, HTTPException, status from app.schemas import AssetExtractRequest, AssetExtractResponse, ErrorResponse from app.services.asset_service import AssetExtractError, extract_assets from app.services.fetcher import FetchError router = APIRouter() def _log_request(req: AssetExtractRequest, phase: str, **extra) -> None: logger = logging.getLogger(__name__) logger.info("request phase=%s id=%s url=%r groups=%r enrich=%s include_data_uris=%s extra=%r", phase, req._request_id or "?", req.url, req.groups, req.enrich, req.include_data_uris, extra) def _log_response(req: AssetExtractRequest, status_code: int, phase: str, **extra) -> None: logger = logging.getLogger(__name__) logger.info("response phase=%s status=%s id=%s url=%r extra=%r", phase, status_code, req._request_id or "?", req.url, extra) @router.post("/assets", response_model=AssetExtractResponse) async def extract_assets_endpoint(req: AssetExtractRequest) -> AssetExtractResponse: """Extract assets from a URL, grouped by category.""" _log_request(req, "start") req_id = req._request_id or str(uuid.uuid4()) try: result = await extract_assets( url=req.url, include_data_uris=req.include_data_uris, enrich=req.enrich, groups=req.groups, ) _log_response(req, 200, "ok", total=result.total) return result except AssetExtractError as exc: _log_response(req, 502, "asset_extract_error", detail=str(exc)) stages = None if hasattr(exc, '__cause__') and isinstance(exc.__cause__, FetchError): stages = exc.__cause__.stages raise HTTPException( status_code=status.HTTP_502_BAD_GATEWAY, detail=ErrorResponse( error="asset extraction failed", code=502, detail=str(exc), request_id=req_id, stages=stages, ).model_dump(), ) from exc except Exception as exc: _log_response(req, 500, "unexpected_error", detail=str(exc)) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=ErrorResponse( error="unexpected server error", code=500, detail=str(exc), request_id=req_id, ).model_dump(), ) from exc @router.get("/health") async def health_check() -> dict[str, str]: return {"status": "ok", "endpoint": "/assets"}