How to add background tasks when request fails and HTTPException is raised in FastAPI?

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.

Leave a Comment