How can I have my error handlers in a separate module cleanly? My current fix for this is to do what this stackoverflow answer says in the first section. I don't necessarily like having to create the app first and then do the import of the error handler module though. I would like to be able to have all my imports before any code is actually run (essentially I don't want to have circular dependencies).
I found these different doc sections in FastAPI docs, but couldn't find anything about having error handlers in a separate module.
I do notice that in the link talking about bigger applications it says it is the equivalent of blueprints. Flask blueprints allow me to put error handlers in a separate module, so am I missing something or does this feature not exist yet?
@joe-eklund
Hi! Since FastAPI does nothing with Starlette's error handling system, except for registering some handlers for its own exceptions, you can use the Starlette.add_exception_handler method instead of the Starlette.exception_handler decorator to register new handlers.
Here is a small example, also you can look here:
from fastapi import FastAPI
from starlette.requests import Request
from starlette.responses import JSONResponse
app = FastAPI()
async def my_handler_for_runtime_error(
request: Request, exc: RuntimeError
) -> JSONResponse:
return JSONResponse(content={"error_type": "runtime_error"}, status_code=500)
@app.get("/")
async def buggy_route() -> None:
raise RuntimeError("error")
app.add_exception_handler(RuntimeError, my_handler_for_runtime_error)
Thank you @nsidnev! That worked perfectly.
Yeah, another approach is to put the error-handler-adding decorators inside a function. Adapting the fastapi docs code, it could look something like this:
# error_handler.py
from fastapi import FastAPI
def add_unicorn_exception_handler(app: FastAPI) -> None:
@app.exception_handler(UnicornException)
async def unicorn_exception_handler(request: Request, exc: UnicornException):
return JSONResponse(
status_code=418,
content={"message": f"Oops! {exc.name} did something. There goes a rainbow..."},
)
from error_handler import add_unicorn_exception_handler
app = FastAPI()
...
add_unicorn_exception_handler(app)
You can follow this pattern to create functions that add your start-up events, shut-down events, and other app initialization. For example, I use it to simplify the operation IDs in my generated OpenAPI schemas (so my generated clients are nicer to work with):
from fastapi import FastAPI
from fastapi.routing import APIRoute
def simplify_operation_ids(app: FastAPI) -> None:
""" Simplify operation IDs so that generated clients have simpler api function names """
for route in app.routes:
if isinstance(route, APIRoute):
route.operation_id = route.name
Thanks for the help here everyone! :cake: :bowing_man:
Thanks @joe-eklund for reporting back and closing the issue :+1:
Most helpful comment
Yeah, another approach is to put the error-handler-adding decorators inside a function. Adapting the fastapi docs code, it could look something like this:
You can follow this pattern to create functions that add your start-up events, shut-down events, and other app initialization. For example, I use it to simplify the operation IDs in my generated OpenAPI schemas (so my generated clients are nicer to work with):