Skip to content

Commit d322ac4

Browse files
committed
Log unhandled 5xx exceptions instead of silently swallowing them in request handlers (#17)
1 parent 9484ee0 commit d322ac4

1 file changed

Lines changed: 28 additions & 13 deletions

File tree

fastopenapi/routers/base.py

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import inspect
2+
import logging
23
import re
34
import threading
45
from abc import ABC, abstractmethod
@@ -18,6 +19,8 @@
1819
BaseRequestDataExtractor,
1920
)
2021

22+
logger = logging.getLogger("fastopenapi")
23+
2124

2225
class BaseAdapter(BaseRouter, ABC):
2326
"""Base adapter for framework integration"""
@@ -93,13 +96,7 @@ def handle_request(self, endpoint: Callable[..., Any], env: RequestEnvelope) ->
9396
response.content = None
9497
return self.build_framework_response(response)
9598
except Exception as e:
96-
api_error = APIError.from_exception(e, self.EXCEPTION_MAPPER)
97-
return self.build_framework_response(
98-
Response(
99-
content=api_error.to_response(),
100-
status_code=api_error.status_code,
101-
)
102-
)
99+
return self.handle_exception(e)
103100

104101
async def handle_request_async(
105102
self, endpoint: Callable[..., Any], env: RequestEnvelope
@@ -125,10 +122,28 @@ async def handle_request_async(
125122
response.content = None
126123
return self.build_framework_response(response)
127124
except Exception as e:
128-
api_error = APIError.from_exception(e, self.EXCEPTION_MAPPER)
129-
return self.build_framework_response(
130-
Response(
131-
content=api_error.to_response(),
132-
status_code=api_error.status_code,
133-
)
125+
return self.handle_exception(e)
126+
127+
def handle_exception(self, exc: Exception) -> Any:
128+
"""Convert an exception into a framework response.
129+
130+
Override to customize how errors are turned into responses.
131+
"""
132+
api_error = APIError.from_exception(exc, self.EXCEPTION_MAPPER)
133+
self.log_exception(exc, api_error)
134+
return self.build_framework_response(
135+
Response(
136+
content=api_error.to_response(),
137+
status_code=api_error.status_code,
134138
)
139+
)
140+
141+
def log_exception(self, exc: Exception, api_error: APIError) -> None:
142+
"""Log unexpected server faults.
143+
144+
Only server errors (status >= 500) are logged with a traceback;
145+
intentional 4xx responses are left untouched. Override to redirect
146+
logging (e.g. Sentry) or to silence it entirely.
147+
"""
148+
if api_error.status_code >= 500:
149+
logger.error("Unhandled exception while processing request", exc_info=exc)

0 commit comments

Comments
 (0)