refactor: Remove duplicate router-level exception helpers
All routers now let domain exceptions propagate to the global handlers in main.py instead of catching and converting them to HTTPException. This eliminates: - Duplicate exception-to-HTTP-status mappings across 8 routers - Duplicate helper functions (_bad_gateway, _not_found, _conflict, etc.) - Inconsistent error response formats Changes: - Removed all try/except blocks from routers that catch domain exceptions - Removed duplicate helper functions from all routers - Added missing exception handlers to main.py for: * ActionNameError * FilterNameError * JailNameError * JailNotFoundInConfigError * FilterInvalidRegexError - Removed unused imports from affected routers All domain exceptions now propagate to the single authoritative mapping in main.py, ensuring consistent error codes, messages, and logging across the API. Affected routers: - action_config.py: Removed _action_not_found, _bad_request, _not_found helpers - bans.py: Removed try/except in ban/unban endpoints - config_misc.py: Removed try/except blocks - file_config.py: Removed 6 try/except blocks and _service_unavailable helper - filter_config.py: Removed try/except blocks - geo.py: Removed try/except in lookup_ip endpoint - jail_config.py: Removed try/except blocks - jails.py: Removed try/except blocks - server.py: Removed try/except blocks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -31,23 +31,31 @@ from app import __version__
|
||||
from app.config import Settings, get_settings
|
||||
from app.exceptions import (
|
||||
ActionAlreadyExistsError,
|
||||
ActionNameError,
|
||||
ActionNotFoundError,
|
||||
ActionReadonlyError,
|
||||
ConfigDirError,
|
||||
ConfigFileExistsError,
|
||||
ConfigFileNameError,
|
||||
ConfigFileNotFoundError,
|
||||
ConfigFileWriteError,
|
||||
ConfigOperationError,
|
||||
ConfigValidationError,
|
||||
ConfigWriteError,
|
||||
Fail2BanConnectionError,
|
||||
Fail2BanProtocolError,
|
||||
FilterAlreadyExistsError,
|
||||
FilterInvalidRegexError,
|
||||
FilterNameError,
|
||||
FilterNotFoundError,
|
||||
FilterReadonlyError,
|
||||
JailAlreadyActiveError,
|
||||
JailAlreadyInactiveError,
|
||||
JailNameError,
|
||||
JailNotFoundError,
|
||||
JailNotFoundInConfigError,
|
||||
JailOperationError,
|
||||
ServerOperationError,
|
||||
)
|
||||
from app.routers import (
|
||||
auth,
|
||||
@@ -308,6 +316,56 @@ async def _domain_error_handler(
|
||||
)
|
||||
|
||||
|
||||
async def _value_error_handler(
|
||||
request: Request,
|
||||
exc: ValueError,
|
||||
) -> JSONResponse:
|
||||
"""Return a ``400 Bad Request`` response for validation and value errors.
|
||||
|
||||
Args:
|
||||
request: The incoming FastAPI request.
|
||||
exc: The :class:`ValueError`.
|
||||
|
||||
Returns:
|
||||
A :class:`fastapi.responses.JSONResponse` with status 400.
|
||||
"""
|
||||
log.warning(
|
||||
"value_error",
|
||||
path=request.url.path,
|
||||
method=request.method,
|
||||
error=str(exc),
|
||||
)
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
content={"detail": str(exc)},
|
||||
)
|
||||
|
||||
|
||||
async def _service_unavailable_handler(
|
||||
request: Request,
|
||||
exc: Exception,
|
||||
) -> JSONResponse:
|
||||
"""Return a ``503 Service Unavailable`` response for infrastructure errors.
|
||||
|
||||
Args:
|
||||
request: The incoming FastAPI request.
|
||||
exc: The infrastructure exception (e.g., ConfigDirError).
|
||||
|
||||
Returns:
|
||||
A :class:`fastapi.responses.JSONResponse` with status 503.
|
||||
"""
|
||||
log.warning(
|
||||
"service_unavailable",
|
||||
path=request.url.path,
|
||||
method=request.method,
|
||||
error=str(exc),
|
||||
)
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
content={"detail": str(exc)},
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Setup-redirect middleware
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -426,12 +484,19 @@ def create_app(settings: Settings | None = None) -> FastAPI:
|
||||
app.add_exception_handler(Fail2BanConnectionError, _fail2ban_connection_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(Fail2BanProtocolError, _fail2ban_protocol_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(JailNotFoundError, _not_found_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(JailNotFoundInConfigError, _not_found_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(FilterNotFoundError, _not_found_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(ActionNotFoundError, _not_found_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(ConfigFileNotFoundError, _not_found_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(ConfigValidationError, _bad_request_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(ConfigFileNameError, _bad_request_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(ConfigOperationError, _bad_request_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(ServerOperationError, _bad_request_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(ActionNameError, _bad_request_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(FilterNameError, _bad_request_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(JailNameError, _bad_request_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(FilterInvalidRegexError, _bad_request_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(ValueError, _value_error_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(JailOperationError, _conflict_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(JailAlreadyActiveError, _conflict_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(JailAlreadyInactiveError, _conflict_handler) # type: ignore[arg-type]
|
||||
@@ -441,6 +506,8 @@ def create_app(settings: Settings | None = None) -> FastAPI:
|
||||
app.add_exception_handler(ActionReadonlyError, _conflict_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(ConfigFileExistsError, _conflict_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(ConfigWriteError, _domain_error_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(ConfigDirError, _service_unavailable_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(ConfigFileWriteError, _bad_request_handler) # type: ignore[arg-type]
|
||||
app.add_exception_handler(Exception, _unhandled_exception_handler)
|
||||
|
||||
# --- Routers ---
|
||||
|
||||
Reference in New Issue
Block a user