The way to do this is to override the HTTPException
error handler, and since there is no BackgroundTasks
object in the exception_handler
, you can add a background task to a response in the way that is described in Starlette documentation (FastAPI is actually Starlette underneath).
Example
from fastapi import BackgroundTasks, FastAPI, HTTPException, Request
from fastapi.responses import PlainTextResponse
from starlette.exceptions import HTTPException as StarletteHTTPException
from starlette.background import BackgroundTask
app = FastAPI()
def write_notification(message):
with open('log.txt', 'a') as f:
f.write(f'{message}'+'\n')
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request, exc):
task = BackgroundTask(write_notification, message=exc.detail)
return PlainTextResponse(str(exc.detail), status_code=exc.status_code, background=task)
@app.get("/{msg}")
def send_notification(msg: str, background_tasks: BackgroundTasks):
if "hello" in msg:
raise HTTPException(status_code=500, detail="Something went wrong")
background_tasks.add_task(write_notification, message="Success")
return {"message": "Request has been successfully submitted."}
If you need to add multiple background tasks to a response, then use:
from fastapi import BackgroundTasks
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request, exc):
tasks = BackgroundTasks()
tasks.add_task(write_notification, message=exc.detail)
tasks.add_task(some_other_function, message="some other message")
return PlainTextResponse(str(exc.detail), status_code=exc.status_code, background=tasks)
A variation of the above approach is the following (suggested here):
from starlette.background import BackgroundTask
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request, exc):
response = PlainTextResponse(str(exc.detail), status_code=exc.status_code)
response.background = BackgroundTask(write_notification, message=exc.detail)
# to add multiple background tasks use:
# response.background = tasks # create `tasks` as shown in the code above
return response
Here are some references that you might also helpful: (1) this answer demonstrates how to add custom exception handlers and (2) this answer shows a custom logging system for the incoming requests and outgoing responses.