diff --git a/CHANGELOG.md b/CHANGELOG.md index b8ca7c7..b9c4ba9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.19 + +* **Add more granular error response texts and codes** + ## 0.0.18 * **Receive ingest 0.3.12** diff --git a/unstructured_platform_plugins/__version__.py b/unstructured_platform_plugins/__version__.py index 4c92910..e52f64f 100644 --- a/unstructured_platform_plugins/__version__.py +++ b/unstructured_platform_plugins/__version__.py @@ -1 +1 @@ -__version__ = "0.0.18" # pragma: no cover +__version__ = "0.0.19" # pragma: no cover diff --git a/unstructured_platform_plugins/etl_uvicorn/api_generator.py b/unstructured_platform_plugins/etl_uvicorn/api_generator.py index dd1e503..0920a62 100644 --- a/unstructured_platform_plugins/etl_uvicorn/api_generator.py +++ b/unstructured_platform_plugins/etl_uvicorn/api_generator.py @@ -15,6 +15,7 @@ from uvicorn.config import LOG_LEVELS from uvicorn.importer import import_from_string +from unstructured_platform_plugins.etl_uvicorn.errors import wrap_error from unstructured_platform_plugins.etl_uvicorn.otel import get_metric_provider, get_trace_provider from unstructured_platform_plugins.etl_uvicorn.utils import ( get_func, @@ -186,12 +187,12 @@ async def _stream_response(): ) except Exception as invoke_error: logger.error(f"failed to invoke plugin: {invoke_error}", exc_info=True) + http_error = wrap_error(invoke_error) return InvokeResponse( usage=usage, filedata_meta=filedata_meta_model.model_validate(filedata_meta.model_dump()), - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - status_code_text=f"failed to invoke plugin: " - f"[{invoke_error.__class__.__name__}] {invoke_error}", + status_code=http_error.status_code, + status_code_text=f"[{invoke_error.__class__.__name__}] {invoke_error}", ) if input_schema_model.model_fields: diff --git a/unstructured_platform_plugins/etl_uvicorn/errors.py b/unstructured_platform_plugins/etl_uvicorn/errors.py new file mode 100644 index 0000000..ebc4ae0 --- /dev/null +++ b/unstructured_platform_plugins/etl_uvicorn/errors.py @@ -0,0 +1,51 @@ +from abc import ABC +from typing import Any, Optional + +import unstructured_ingest.v2.errors as ingest_errors +from fastapi import HTTPException + + +class BaseError(HTTPException, ABC): + status_code: int + + def __init__(self, detail: Any, headers: Optional[dict[str, str]] = None): + super().__init__(status_code=self.status_code, detail=detail, headers=headers) + + +class UserError(BaseError): + status_code: int = 400 + + +class UserAuthError(UserError): + status_code: int = 403 + + +class RateLimitError(UserError): + status_code: int = 429 + + +class QuotaError(UserError): + status_code: int = 402 + + +class ProviderError(BaseError): + status_code: int = 500 + + +class CatchAllError(BaseError): + status_code: int = 512 + + +def wrap_error(e: Exception) -> HTTPException: + if isinstance(e, ingest_errors.UserAuthError): + return UserAuthError(e) + elif isinstance(e, ingest_errors.RateLimitError): + return RateLimitError(e) + elif isinstance(e, ingest_errors.QuotaError): + return QuotaError(e) + elif isinstance(e, ingest_errors.UserError): + return UserError(e) + elif isinstance(e, ingest_errors.ProviderError): + return ProviderError(e) + else: + return CatchAllError(e)