Created
June 16, 2026 20:04
-
-
Save digoreis/5b26e730a7b1043767d727c59f689ac2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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