Skip to main content

Application Core

The FastAPI class is the central entry point for creating and configuring your application. It inherits from Starlette and extends it with features like automatic OpenAPI generation, dependency injection, and data validation.

The FastAPI Application

You create a FastAPI application by instantiating the FastAPI class. This instance is used to define routes, handle events, and configure global settings.

from fastapi import FastAPI

app = FastAPI(
title="ChimichangApp",
description="API description",
version="0.0.1",
)

@app.get("/")
async def read_main():
return {"msg": "Hello World"}

The FastAPI constructor in fastapi/applications.py accepts several parameters to customize the application's metadata and behavior:

  • title: The name of the API, displayed in the automatic documentation.
  • description: A detailed description of the API, supporting Markdown.
  • version: The version of your application (e.g., 1.2.3).
  • summary: A short summary of the API.
  • debug: If set to True, the server will return detailed error tracebacks to the client on 500 errors.

Lifecycle Management

FastAPI uses a lifespan context manager to handle logic that should run before the application starts and after it shuts down. This is the preferred way to manage resources like database connection pools or machine learning models.

The lifespan parameter in the FastAPI constructor expects an asynccontextmanager.

from contextlib import asynccontextmanager
from fastapi import FastAPI

@asynccontextmanager
async def lifespan(app: FastAPI):
# Load the ML model or connect to a database
print("Startup: Resources initialized")
yield
# Clean up resources
print("Shutdown: Resources cleaned up")

app = FastAPI(lifespan=lifespan)

Internally, FastAPI passes this lifespan handler to the underlying Starlette application. While legacy on_startup and on_shutdown event handlers are still supported for backward compatibility, lifespan is recommended as it provides a cleaner way to handle the full lifecycle in a single block.

Routing and Modularization

FastAPI provides decorators for all standard HTTP methods to define "path operations." These methods are implemented in both the FastAPI class and the APIRouter class.

Path Operation Decorators

You define endpoints using decorators like @app.get(), @app.post(), @app.put(), and @app.delete().

@app.post("/items/")
async def create_item(item_id: int):
return {"item_id": item_id}

Organizing with APIRouter

For larger applications, you can use APIRouter (defined in fastapi/routing.py) to group related endpoints into separate files or modules. You then include these routers in the main application using include_router.

from fastapi import APIRouter, FastAPI

app = FastAPI()
router = APIRouter()

@router.get("/users/")
async def read_users():
return [{"username": "Rick"}, {"username": "Morty"}]

app.include_router(router, prefix="/api/v1", tags=["users"])

When you call app.include_router(), FastAPI merges the router's paths into the main application's routing table. You can provide a prefix (e.g., /api/v1) and tags that will be applied to all routes within that router.

Global Configuration

FastAPI allows you to configure behavior that applies to the entire application, such as error handling and middleware.

Exception Handlers

You can define custom logic for handling specific exceptions using the @app.exception_handler() decorator. This is useful for returning consistent error responses when specific errors occur.

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

class UnicornException(Exception):
pass

app = FastAPI()

@app.exception_handler(UnicornException)
async def unicorn_exception_handler(request: Request, exc: UnicornException):
return JSONResponse(
status_code=418,
content={"message": "Oops! A unicorn appeared."},
)

Middleware

Middleware allows you to process requests before they reach your path operations and modify responses before they are sent to the client. You can add middleware using the @app.middleware("http") decorator or the add_middleware() method.

import time
from fastapi import FastAPI, Request

app = FastAPI()

@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response

The middleware decorator internally uses self.add_middleware(BaseHTTPMiddleware, dispatch=func) to register the function.

Proxy and Documentation Settings

When deploying FastAPI behind a proxy (like Nginx or Traefik), the application might need to know the "root path" to generate correct URLs for the documentation and internal links.

Root Path

If your app is served under a prefix like /api/v1 by a proxy, but the app itself is mounted at /, the Swagger UI will fail to load the OpenAPI schema because it will look for /openapi.json instead of /api/v1/openapi.json. Passing root_path fixes this:

app = FastAPI(root_path="/api/v1")

Documentation URLs

By default, FastAPI serves the OpenAPI schema and interactive documentation at specific paths. You can change or disable these in the FastAPI constructor:

  • openapi_url: Defaults to /openapi.json. Set to None to disable OpenAPI generation.
  • docs_url: Defaults to /docs (Swagger UI).
  • redoc_url: Defaults to /redoc (ReDoc).
app = FastAPI(openapi_url="/api/v1/openapi.json", docs_url="/documentation")