api / app /routers /assets.py
lljz66's picture
Put app/routers/assets.py
7ea950d verified
Raw
History Blame Contribute Delete
2.7 kB
"""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"}