FastAPI Production Patterns
App Structure with Lifespan
from fastapi import FastAPI
from contextlib import asynccontextmanager
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
await database.connect()
yield
# Shutdown
await database.disconnect()
app = FastAPI(lifespan=lifespan)
Async Endpoints
from fastapi import FastAPI, Depends
from sqlalchemy.ext.asyncio import AsyncSession
@app.get("/users/{user_id}")
async def get_user(
user_id: int,
db: AsyncSession = Depends(get_db)
):
user = await db.get(User, user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
Pydantic Models with Validation
from pydantic import BaseModel, validator, Field
class UserCreate(BaseModel):
email: str = Field(..., example="user@example.com")
age: int = Field(..., ge=0, le=150)
@validator('email')
def validate_email(cls, v):
if '@' not in v or '.' not in v.split('@')[1]:
raise ValueError('Invalid email format')
return v.lower()
class Config:
orm_mode = True
Dependency Injection
from sqlalchemy.ext.asyncio import AsyncSession
async def get_db() -> AsyncSession:
async with AsyncSessionLocal() as session:
yield session
async def get_current_user(
token: str = Depends(oauth2_scheme),
db: AsyncSession = Depends(get_db)
):
user = await verify_token(token, db)
return user
@app.get("/me")
async def read_users_me(
current_user: User = Depends(get_current_user)
):
return current_user
CORS Middleware
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["https://yourdomain.com"],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["*"],
)
Error Handling
from fastapi import Request
from fastapi.responses import JSONResponse
@app.exception_handler(ValueError)
async def value_error_handler(request: Request, exc: ValueError):
return JSONResponse(
status_code=400,
content={"detail": str(exc)}
)
class CustomException(Exception):
def __init__(self, name: str):
self.name = name
@app.exception_handler(CustomException)
async def custom_exception_handler(request: Request, exc: CustomException):
return JSONResponse(
status_code=418,
content={"message": f"Oops! {exc.name}"}
)
Background Tasks
from fastapi import BackgroundTasks
def send_email(email: str, message: str):
# Send email logic
pass
@app.post("/send-notification/")
async def send_notification(
email: str,
background_tasks: BackgroundTasks
):
background_tasks.add_task(send_email, email, "notification")
return {"message": "Notification sent in background"}
File Upload
from fastapi import File, UploadFile
@app.post("/upload/")
async def upload_file(file: UploadFile = File(...)):
contents = await file.read()
# Process file
return {"filename": file.filename, "size": len(contents)}
Scripts
scripts/skill_info.py: Print skill name and description.