|
134 | 134 | from mcpgateway.services.a2a_service import A2AAgentError, A2AAgentNameConflictError, A2AAgentNotFoundError, A2AAgentService |
135 | 135 | from mcpgateway.services.cancellation_service import cancellation_service |
136 | 136 | from mcpgateway.services.completion_service import CompletionService |
| 137 | +from mcpgateway.services.content_security import ContentSizeError |
137 | 138 | from mcpgateway.services.email_auth_service import EmailAuthService |
138 | 139 | from mcpgateway.services.export_service import ExportError, ExportService |
139 | 140 | from mcpgateway.services.gateway_service import GatewayConnectionError, GatewayDuplicateConflictError, GatewayError, GatewayNameConflictError, GatewayNotFoundError |
@@ -2151,6 +2152,20 @@ async def database_exception_handler(_request: Request, exc: IntegrityError): |
2151 | 2152 | return ORJSONResponse(status_code=409, content=ErrorFormatter.format_database_error(exc)) |
2152 | 2153 |
|
2153 | 2154 |
|
| 2155 | +@app.exception_handler(ContentSizeError) |
| 2156 | +async def content_size_exception_handler(_request: Request, exc: ContentSizeError): |
| 2157 | + """Handle content size limit violations globally. |
| 2158 | +
|
| 2159 | + Args: |
| 2160 | + _request: The incoming request (unused, required by FastAPI handler interface). |
| 2161 | + exc: The ContentSizeError with actual_size, max_size, and content_type. |
| 2162 | +
|
| 2163 | + Returns: |
| 2164 | + ORJSONResponse: A 413 Payload Too Large response with structured error details. |
| 2165 | + """ |
| 2166 | + return ORJSONResponse(status_code=413, content={"detail": {"error": f"{exc.content_type} size limit exceeded", "message": str(exc), "actual_size": exc.actual_size, "max_size": exc.max_size}}) |
| 2167 | + |
| 2168 | + |
2154 | 2169 | # RFC 9110 §5.6.2 'token' pattern for header field names: |
2155 | 2170 | # token = 1*tchar |
2156 | 2171 | # tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" |
@@ -5411,6 +5426,9 @@ async def create_resource( |
5411 | 5426 | except IntegrityError as e: |
5412 | 5427 | logger.error(f"Integrity error while creating resource: {e}") |
5413 | 5428 | raise HTTPException(status_code=409, detail=ErrorFormatter.format_database_error(e)) |
| 5429 | + except ContentSizeError as e: |
| 5430 | + logger.error(f"Content size exceeded in creating resource: {e}") |
| 5431 | + raise HTTPException(status_code=413, detail={"error": f"{e.content_type} size limit exceeded", "message": str(e), "actual_size": e.actual_size, "max_size": e.max_size}) |
5414 | 5432 |
|
5415 | 5433 |
|
5416 | 5434 | @resource_router.get("/{resource_id}") |
@@ -5591,6 +5609,9 @@ async def update_resource( |
5591 | 5609 | raise HTTPException(status_code=409, detail=ErrorFormatter.format_database_error(e)) |
5592 | 5610 | except ResourceURIConflictError as e: |
5593 | 5611 | raise HTTPException(status_code=409, detail=str(e)) |
| 5612 | + except ContentSizeError as e: |
| 5613 | + logger.error(f"Content size exceeded in updating resource: {e}") |
| 5614 | + raise HTTPException(status_code=413, detail={"error": f"{e.content_type} size limit exceeded", "message": str(e), "actual_size": e.actual_size, "max_size": e.max_size}) |
5594 | 5615 | db.commit() |
5595 | 5616 | db.close() |
5596 | 5617 | await invalidate_resource_cache(resource_id) |
@@ -5915,6 +5936,9 @@ async def create_prompt( |
5915 | 5936 | # If there is an integrity error, return a 409 Conflict error |
5916 | 5937 | logger.error(f"Integrity error while creating prompt: {e}") |
5917 | 5938 | raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=ErrorFormatter.format_database_error(e)) |
| 5939 | + if isinstance(e, ContentSizeError): |
| 5940 | + logger.error(f"Content size exceeded in creating prompt: {e}") |
| 5941 | + raise HTTPException(status_code=413, detail={"error": f"{e.content_type} size limit exceeded", "message": str(e), "actual_size": e.actual_size, "max_size": e.max_size}) |
5918 | 5942 | # For any other unexpected errors, return a 500 Internal Server Error |
5919 | 5943 | logger.error(f"Unexpected error while creating prompt: {e}") |
5920 | 5944 | raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="An unexpected error occurred while creating the prompt") |
@@ -6109,6 +6133,9 @@ async def update_prompt( |
6109 | 6133 | if isinstance(e, PromptError): |
6110 | 6134 | # If there is a general prompt error, return a 400 Bad Request error |
6111 | 6135 | raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) |
| 6136 | + if isinstance(e, ContentSizeError): |
| 6137 | + logger.error(f"Content size exceeded in updating prompt: {e}") |
| 6138 | + raise HTTPException(status_code=413, detail={"error": f"{e.content_type} size limit exceeded", "message": str(e), "actual_size": e.actual_size, "max_size": e.max_size}) |
6112 | 6139 | # For any other unexpected errors, return a 500 Internal Server Error |
6113 | 6140 | logger.error(f"Unexpected error while updating prompt: {e}") |
6114 | 6141 | raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="An unexpected error occurred while updating the prompt") |
|
0 commit comments