diff --git a/gliner_inference_server/main.py b/gliner_inference_server/main.py index f4f34de..bf1abec 100644 --- a/gliner_inference_server/main.py +++ b/gliner_inference_server/main.py @@ -1,4 +1,6 @@ from fastapi import FastAPI, HTTPException, status +from fastapi.responses import JSONResponse +from starlette.requests import Request from typing import List, Optional, Union, Dict, Any, Tuple from contextlib import asynccontextmanager import os @@ -31,6 +33,41 @@ app = FastAPI( lifespan=lifespan ) +@app.exception_handler(HTTPException) +async def http_exception_handler(request: Request, exc: HTTPException): + """ + Handles FastAPI's HTTPException to enforce a consistent, flat error + response structure (removing the default 'detail' wrapping). + + The handler expects 'exc.detail' to be a dictionary containing the + desired error structure with the key 'error' (e.g., {"error": {...}}). + + :param request: The incoming request object. + :param exc: The HTTPException instance raised (e.g., in validate_single_or_batch). + :return: A JSONResponse object with the custom error body and the correct status code. + """ + + # Determine the content to be returned in the response body + if isinstance(exc.detail, dict) and "error" in exc.detail: + # If the detail matches the expected custom format (e.g., {"error": {...}}), + # use the entire dictionary as the response content. + response_body = exc.detail + else: + # Fallback for unexpected or standard FastAPI error formats (e.g., detail is a string). + # Ensures the response always adheres to the expected structure. + response_body = { + "error": { + "code": "GENERIC_ERROR", + "message": str(exc.detail), + "details": {} + } + } + + return JSONResponse( + status_code=exc.status_code, + content=response_body + ) + # ==================== Endpoints ==================== @app.get("/health") async def health_check():