Skip to main content
Advertisement

FastAPI Overview

FastAPI is a modern web framework for building REST APIs quickly using Python 3.8+ type hints. Its key strengths are high performance, automatic documentation, and seamless Pydantic integration.


Where FastAPI Fits

Client (Browser / App)
│ HTTP Request

Uvicorn (ASGI Server) ← Converts HTTP to Python events


Starlette (ASGI Framework) ← Routing, middleware, WebSocket


FastAPI ← Adds type hints + Pydantic + OpenAPI on top of Starlette
# Installation
pip install fastapi uvicorn[standard]

# Optional
pip install python-multipart # File uploads
pip install python-jose[cryptography] # JWT
pip install passlib[bcrypt] # Password hashing
pip install sqlalchemy # ORM

First API

# main.py
from fastapi import FastAPI

app = FastAPI(
title="Learning API",
description="FastAPI learning examples",
version="1.0.0",
)


@app.get("/")
def read_root():
return {"message": "Hello FastAPI"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
# Run dev server
uvicorn main:app --reload

# Access
# API: http://localhost:8000
# Docs: http://localhost:8000/docs (Swagger UI)
# Docs: http://localhost:8000/redoc (ReDoc)

Path, Query, and Body Parameters

from fastapi import FastAPI
from pydantic import BaseModel
from typing import Annotated
from fastapi import Query, Path, Body

app = FastAPI()


# Path parameter
@app.get("/users/{user_id}")
def get_user(user_id: int):
return {"user_id": user_id}


# Query parameter
@app.get("/search")
def search(
q: str,
skip: int = 0,
limit: Annotated[int, Query(ge=1, le=100)] = 10,
):
return {"q": q, "skip": skip, "limit": limit}


# Request body (Pydantic model)
class Item(BaseModel):
name: str
price: float
is_offer: bool = False


@app.post("/items/")
def create_item(item: Item):
return {"item_name": item.name, "price": item.price}


# Combining path + body
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_id": item_id, "item": item}

Response Models and Status Codes

from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel
from typing import Optional

app = FastAPI()


class UserIn(BaseModel):
name: str
email: str
password: str


class UserOut(BaseModel):
id: int
name: str
email: str
# no password field → automatically excluded from response


fake_db: dict[int, dict] = {}
next_id = 1


@app.post(
"/users/",
response_model=UserOut,
status_code=status.HTTP_201_CREATED,
)
def create_user(user: UserIn):
global next_id
user_data = {"id": next_id, "name": user.name, "email": user.email}
fake_db[next_id] = user_data
next_id += 1
return user_data


@app.get("/users/{user_id}", response_model=UserOut)
def get_user(user_id: int):
if user_id not in fake_db:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"User {user_id} not found",
)
return fake_db[user_id]

Async Endpoints

import asyncio
import httpx
from fastapi import FastAPI

app = FastAPI()


# async def: recommended for async I/O
@app.get("/async-example")
async def async_example():
await asyncio.sleep(0.1) # non-blocking wait
return {"result": "async response"}


# Calling external API (httpx async client)
@app.get("/external")
async def call_external():
async with httpx.AsyncClient() as client:
response = await client.get("https://httpbin.org/uuid")
return response.json()


# def vs async def
# - def: runs in thread pool (blocking OK)
# - async def: runs in event loop (must use await)

@app.get("/sync")
def sync_endpoint():
# CPU-bound or legacy synchronous code
return {"type": "sync"}


@app.get("/async")
async def async_endpoint():
# I/O-bound: DB query, HTTP request, file read
await asyncio.sleep(0)
return {"type": "async"}

App Events and Lifespan

from contextlib import asynccontextmanager
from fastapi import FastAPI


# Python 3.9+: use lifespan for startup/shutdown
@asynccontextmanager
async def lifespan(app: FastAPI):
# Run on startup
print("App start: initialize DB connection pool")
app.state.db_pool = {"connected": True}

yield # app is running

# Run on shutdown
print("App stop: clean up DB connection pool")
app.state.db_pool = None


app = FastAPI(lifespan=lifespan)


@app.get("/health")
def health_check():
return {"status": "ok", "db": app.state.db_pool["connected"]}

Summary

ConceptDescription
FastAPIStarlette + Pydantic + OpenAPI integration
UvicornASGI server (fast async HTTP handling)
/docsAuto-generated Swagger UI
response_modelSpecify response schema + auto-filtering
HTTPExceptionHTTP error response
async defAsync endpoint
lifespanApp startup/shutdown event handling

FastAPI's core strength is using type hints for documentation, validation, and serialization all at once.

Advertisement