Skip to content

Instantly share code, notes, and snippets.

@digoreis
Created June 16, 2026 20:04
Show Gist options
  • Select an option

  • Save digoreis/5b26e730a7b1043767d727c59f689ac2 to your computer and use it in GitHub Desktop.

Select an option

Save digoreis/5b26e730a7b1043767d727c59f689ac2 to your computer and use it in GitHub Desktop.
# Creating API with FastAPI in Python
**Session ID:** ses_12dfdb881ffeioJrmJormLiWXn
**Created:** 6/16/2026, 8:57:05 PM
**Updated:** 6/16/2026, 9:01:04 PM
---
## User
Please show how to create a API with FastAPI in Python
---
## Assistant (Build · default_model · 23.7s)
_Thinking:_
The user is asking for a general explanation of how to create a FastAPI application. This is a straightforward educational request about a popular Python web framework. I should provide a concise, practical example showing the key components of a FastAPI application.
# Creating a FastAPI Application
FastAPI is a modern, fast (high-performance) web framework for building APIs with Python 3.8+ based on standard Python type hints.
## Basic Setup
```bash
pip install fastapi uvicorn
```
## Simple API Example
```python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
# Pydantic model for request validation
class Item(BaseModel):
name: str
price: float
is_active: bool = True
# Simple endpoint
@app.get("/")
def read_root():
return {"message": "Hello, World!"}
@app.get("/items/{item_id}")
def read_item(item_id: int, item_name: str):
return {"item_id": item_id, "name": item_name}
@app.post("/items")
def create_item(item: Item):
return {"item": item}
```
## Run the Server
```bash
uvicorn main:app --reload
```
## Key Features
- **Type hints** for automatic documentation
- **Automatic OpenAPI/Swagger docs** at `/docs`
- **Request validation** with Pydantic
- **Async support** for high performance
- **Automatic response models**
## Common Endpoints
| Method | Path | Description |
|--------|------|-------------|
| GET | `/` | Root endpoint |
| GET | `/items/{id}` | Get item by ID |
| POST | `/items` | Create new item |
| PUT | `/items/{id}` | Update item |
| DELETE | `/items/{id}` | Delete item |
Would you like me to create a more complete example with database integration or specific features?
---
## User
please I would like a middleware for authentication the requests with API key in the header
---
## Assistant (Build · default_model · 30.7s)
_Thinking:_
The user wants to add API key authentication middleware to a FastAPI application. I should provide a complete example showing how to create middleware that validates API keys from request headers.
# API Key Authentication Middleware for FastAPI
Here's a complete example with authentication middleware:
## `main.py`
```python
from fastapi import FastAPI, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import os
app = FastAPI()
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# API Key configuration
API_KEY = os.getenv("API_KEY", "your-secret-api-key")
# Pydantic models
class Item(BaseModel):
name: str
price: float
is_active: bool = True
# Authentication middleware
@app.middleware("http")
async def api_key_middleware(request, call_next):
api_key = request.headers.get("X-API-Key")
if not api_key or api_key != API_KEY:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid API key",
headers={"WWW-Authenticate": "ApiKey"},
)
response = await call_next(request)
return response
# Endpoints
@app.get("/")
def read_root():
return {"message": "Hello, World!"}
@app.get("/items/{item_id}")
def read_item(item_id: int, item_name: str):
return {"item_id": item_id, "name": item_name}
@app.post("/items")
def create_item(item: Item):
return {"item": item}
```
## Environment Setup
```bash
# Create .env file
echo "API_KEY=your-secret-api-key" > .env
# Or set directly
export API_KEY=your-secret-api-key
```
## Usage
```bash
# Start server
uvicorn main:app --reload
# Test with valid API key
curl -H "X-API-Key: your-secret-api-key" http://localhost:8000/items
# Test with invalid API key (will return 401)
curl -H "X-API-Key: wrong-key" http://localhost:8000/items
```
## Alternative: Using Header Name
If you prefer a different header name:
```python
# Change this line
api_key = request.headers.get("X-API-Key")
# To use "Authorization" header
api_key = request.headers.get("Authorization")
```
## Production Tips
1. **Store API key in environment variables** (never commit to git)
2. **Use HTTPS** in production
3. **Rate limiting** to prevent abuse
4. **Consider JWT** for more complex auth needs
Would you like me to add rate limiting or JWT authentication instead?
---
## User
A rate limite sounds good
---
## Assistant (Build · default_model · 43.4s)
_Thinking:_
The user wants to add rate limiting to the FastAPI application with API key authentication. I should add a rate limiter middleware that works with the API key. I'll use a simple in-memory approach for demonstration, but mention that for production they should use a proper rate limiting library like FastAPI's built-in rate limit middleware or redis-based solutions.
# Adding Rate Limiting to FastAPI with API Key
Here's the complete implementation with rate limiting:
## `main.py`
```python
from fastapi import FastAPI, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from pydantic import BaseModel
import os
from collections import defaultdict
from datetime import datetime, timedelta
import time
app = FastAPI()
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# API Key configuration
API_KEY = os.getenv("API_KEY", "your-secret-api-key")
# Rate limiting configuration
RATE_LIMIT = 100 # requests per minute
RATE_LIMIT_WINDOW = 60 # seconds
# In-memory rate limit storage
rate_limits = defaultdict(lambda: {"count": 0, "window_start": time.time()})
# Pydantic models
class Item(BaseModel):
name: str
price: float
is_active: bool = True
# Check rate limit
def check_rate_limit(api_key: str):
current_time = time.time()
window_start = current_time - RATE_LIMIT_WINDOW
if api_key not in rate_limits:
rate_limits[api_key] = {"count": 0, "window_start": current_time}
rate_limits[api_key]["window_start"] = max(rate_limits[api_key]["window_start"], window_start)
rate_limits[api_key]["count"] += 1
if rate_limits[api_key]["count"] > RATE_LIMIT:
return False, "Too many requests"
return True, None
# Authentication middleware
@app.middleware("http")
async def api_key_middleware(request, call_next):
api_key = request.headers.get("X-API-Key")
if not api_key or api_key != API_KEY:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid API key",
headers={"WWW-Authenticate": "ApiKey"},
)
# Check rate limit
allowed, error = check_rate_limit(api_key)
if not allowed:
return JSONResponse(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
content={"detail": error},
headers={"Retry-After": str(RATE_LIMIT_WINDOW)}
)
response = await call_next(request)
return response
# Endpoints
@app.get("/")
def read_root():
return {"message": "Hello, World!"}
@app.get("/items/{item_id}")
def read_item(item_id: int, item_name: str):
return {"item_id": item_id, "name": item_name}
@app.post("/items")
def create_item(item: Item):
return {"item": item}
```
## Environment Setup
```bash
# Create .env file
echo "API_KEY=your-secret-api-key" > .env
echo "RATE_LIMIT=100" >> .env
echo "RATE_LIMIT_WINDOW=60" >> .env
```
## Usage
```bash
# Start server
uvicorn main:app --reload
# Test with valid API key
curl -H "X-API-Key: your-secret-api-key" http://localhost:8000/items
# Test rate limiting (make many requests quickly)
for i in {1..105}; do
curl -H "X-API-Key: your-secret-api-key" http://localhost:8000/items
done
```
## Production Recommendations
For production, consider using:
1. **Redis-based rate limiting** (more reliable)
2. **FastAPI's built-in rate limit middleware**
3. **External rate limiting service** (e.g., Redis, Memcached)
Would you like me to show you a Redis-based implementation for production?
---
## User
sounds good
---
## Assistant (Build · default_model · 12.2s)
_Thinking:_
The user seems satisfied with the rate limiting implementation I provided. They said "sounds good" which indicates they're happy with the solution. I should acknowledge this and offer to help with next steps or any additional features they might want.
Great! You now have a complete FastAPI application with:
- ✅ **API Key Authentication** (via `X-API-Key` header)
- ✅ **Rate Limiting** (100 requests per minute)
- ✅ **CORS Support**
- ✅ **Automatic Swagger/OpenAPI docs**
## Quick Start
```bash
# Install dependencies
pip install fastapi uvicorn
# Create .env file
echo "API_KEY=your-secret-api-key" > .env
# Run the server
uvicorn main:app --reload
```
## Test It
```bash
# Valid request
curl -H "X-API-Key: your-secret-api-key" http://localhost:8000/items
# Check docs
http://localhost:8000/docs
```
Let me know if you need anything else!
---
## User
sorry please show the Redis implementation
---
## Assistant (Build · default_model · 47.7s)
_Thinking:_
The user wants to see the Redis-based rate limiting implementation for production. I should show them how to use Redis with FastAPI for rate limiting, which is more reliable than in-memory storage for production environments.
# Redis-Based Rate Limiting for FastAPI
Here's the production-ready implementation with Redis:
## `main.py`
```python
from fastapi import FastAPI, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from pydantic import BaseModel
import os
import redis
import time
app = FastAPI()
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# API Key configuration
API_KEY = os.getenv("API_KEY", "your-secret-api-key")
# Redis connection
redis_client = redis.Redis(
host=os.getenv("REDIS_HOST", "localhost"),
port=int(os.getenv("REDIS_PORT", 6379)),
db=int(os.getenv("REDIS_DB", 0)),
password=os.getenv("REDIS_PASSWORD"),
decode_responses=True
)
# Rate limiting configuration
RATE_LIMIT = int(os.getenv("RATE_LIMIT", "100"))
RATE_LIMIT_WINDOW = int(os.getenv("RATE_LIMIT_WINDOW", "60"))
# Pydantic models
class Item(BaseModel):
name: str
price: float
is_active: bool = True
# Rate limiting with Redis
def check_rate_limit(api_key: str):
current_time = time.time()
window_start = current_time - RATE_LIMIT_WINDOW
# Get current count in window
count = redis_client.incr(f"ratelimit:{api_key}:{window_start}")
if count == 1:
redis_client.expire(f"ratelimit:{api_key}:{window_start}", RATE_LIMIT_WINDOW + 1)
if count > RATE_LIMIT:
return False, "Too many requests"
return True, None
# Authentication middleware
@app.middleware("http")
async def api_key_middleware(request, call_next):
api_key = request.headers.get("X-API-Key")
if not api_key or api_key != API_KEY:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid API key",
headers={"WWW-Authenticate": "ApiKey"},
)
# Check rate limit
allowed, error = check_rate_limit(api_key)
if not allowed:
return JSONResponse(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
content={"detail": error},
headers={"Retry-After": str(RATE_LIMIT_WINDOW)}
)
response = await call_next(request)
return response
# Endpoints
@app.get("/")
def read_root():
return {"message": "Hello, World!"}
@app.get("/items/{item_id}")
def read_item(item_id: int, item_name: str):
return {"item_id": item_id, "name": item_name}
@app.post("/items")
def create_item(item: Item):
return {"item": item}
```
## Setup
### 1. Install Dependencies
```bash
pip install fastapi uvicorn redis
```
### 2. Environment Variables
```bash
# Create .env file
cat > .env << EOF
API_KEY=your-secret-api-key
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_DB=0
RATE_LIMIT=100
RATE_LIMIT_WINDOW=60
EOF
```
### 3. Start Redis (if not running)
```bash
# macOS
brew services start redis
# Or download from https://redis.io/download
```
### 4. Run the Server
```bash
uvicorn main:app --reload
```
## Test It
```bash
# Valid request
curl -H "X-API-Key: your-secret-api-key" http://localhost:8000/items
# Check Redis connection
redis-cli -h localhost ping
# Monitor rate limit
redis-cli -h localhost GET ratelimit:your-secret-api-key:$(date +%s)
```
## Production Tips
1. **Use Redis Sentinel** for high availability
2. **Configure Redis cluster** for scaling
3. **Add monitoring** for rate limit metrics
4. **Consider different limits** per API key tier
Would you like me to add monitoring or tiered rate limiting?
---
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment