agentsclimarketplace

Fastapi

Skill ComeOnOliver/skillshub/skills/TerminalSkills/skills/fastapi

🧠 The right skill, one API call. AI agent skills registry with token-efficient skill resolution. 5,000+ skills from 500+ top repos.

Install
npx -y skills add ComeOnOliver/skillshub --skill fastapi

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

5.8 KB, as published. Nobody here has run it

FastAPI

FastAPI is a Python web framework built on Starlette (ASGI) and Pydantic. It provides automatic request validation, serialization, and interactive API docs at /docs (Swagger UI) and /redoc.

Installation

# Install FastAPI with uvicorn ASGI server
pip install "fastapi[standard]"

Project Structure

# Typical FastAPI project layout
app/
β”œβ”€β”€ main.py           # Application entry point
β”œβ”€β”€ config.py         # Settings and configuration
β”œβ”€β”€ models/           # SQLAlchemy / DB models
β”œβ”€β”€ schemas/          # Pydantic schemas
β”œβ”€β”€ routers/          # API route modules
β”œβ”€β”€ dependencies.py   # Shared dependencies
β”œβ”€β”€ middleware.py     # Custom middleware
└── tests/

Application Setup

# main.py β€” FastAPI application entry point
from fastapi import FastAPI
from contextlib import asynccontextmanager

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup: initialize DB pool, caches, etc.
    yield
    # Shutdown: close connections

app = FastAPI(
    title="My API",
    version="1.0.0",
    lifespan=lifespan,
)

Routes and Path Operations

# routers/items.py β€” CRUD router for items
from fastapi import APIRouter, HTTPException, status, Query, Path
from pydantic import BaseModel, Field

router = APIRouter(prefix="/items", tags=["items"])

class ItemCreate(BaseModel):
    name: str = Field(..., min_length=1, max_length=100)
    price: float = Field(..., gt=0)
    description: str | None = None

class ItemResponse(ItemCreate):
    id: int

    model_config = {"from_attributes": True}

@router.get("/", response_model=list[ItemResponse])
async def list_items(skip: int = Query(0, ge=0), limit: int = Query(20, le=100)):
    return await db.fetch_items(skip=skip, limit=limit)

@router.post("/", response_model=ItemResponse, status_code=status.HTTP_201_CREATED)
async def create_item(item: ItemCreate):
    return await db.create_item(item)

@router.get("/{item_id}", response_model=ItemResponse)
async def get_item(item_id: int = Path(..., gt=0)):
    item = await db.get_item(item_id)
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")
    return item

Dependency Injection

# dependencies.py β€” reusable dependencies
from fastapi import Depends, Header, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession

async def get_db() -> AsyncSession:
    async with async_session() as session:
        yield session

async def get_current_user(authorization: str = Header(...)):
    token = authorization.removeprefix("Bearer ")
    user = await verify_token(token)
    if not user:
        raise HTTPException(status_code=401, detail="Invalid token")
    return user

# Use in routes
@router.get("/me")
async def read_me(user=Depends(get_current_user), db=Depends(get_db)):
    return user

Pydantic Schemas and Validation

# schemas/user.py β€” request/response schemas with validation
from pydantic import BaseModel, EmailStr, field_validator
from datetime import datetime

class UserCreate(BaseModel):
    email: EmailStr
    password: str = Field(..., min_length=8)
    username: str

    @field_validator("username")
    @classmethod
    def username_alphanumeric(cls, v: str) -> str:
        if not v.isalnum():
            raise ValueError("must be alphanumeric")
        return v

class UserResponse(BaseModel):
    id: int
    email: EmailStr
    username: str
    created_at: datetime

    model_config = {"from_attributes": True}

Middleware

# middleware.py β€” custom middleware example
import time
from fastapi import Request

@app.middleware("http")
async def add_timing_header(request: Request, call_next):
    start = time.perf_counter()
    response = await call_next(request)
    elapsed = time.perf_counter() - start
    response.headers["X-Process-Time"] = f"{elapsed:.4f}"
    return response

Background Tasks

# routers/notifications.py β€” background task example
from fastapi import BackgroundTasks

async def send_email(to: str, body: str):
    # Long-running email sending logic
    ...

@router.post("/notify")
async def notify(email: str, bg: BackgroundTasks):
    bg.add_task(send_email, email, "Welcome!")
    return {"status": "queued"}

WebSocket Support

# routers/ws.py β€” WebSocket endpoint
from fastapi import WebSocket, WebSocketDisconnect

@app.websocket("/ws/{client_id}")
async def websocket_endpoint(websocket: WebSocket, client_id: str):
    await websocket.accept()
    try:
        while True:
            data = await websocket.receive_text()
            await websocket.send_text(f"Echo: {data}")
    except WebSocketDisconnect:
        pass

Testing

# tests/test_items.py β€” testing with httpx
from httpx import AsyncClient, ASGITransport
import pytest

@pytest.mark.anyio
async def test_create_item():
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as client:
        resp = await client.post("/items/", json={"name": "Widget", "price": 9.99})
        assert resp.status_code == 201
        assert resp.json()["name"] == "Widget"

Running

# Run development server with auto-reload
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

Key Patterns

  • Use response_model to control output serialization and strip internal fields
  • Group routes with APIRouter and include in main app via app.include_router(router)
  • Use Depends() for DB sessions, auth, pagination β€” they compose and cache per-request
  • Raise HTTPException for error responses; use custom exception handlers for global patterns
  • Use lifespan context manager for startup/shutdown instead of deprecated events
  • Set from_attributes = True in Pydantic config to read from ORM objects

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.