Middleware และ CORS
Middleware ใน FastAPI
หัวข้อที่มีชื่อว่า “Middleware ใน FastAPI”ใน Express app.use(fn) ลงทะเบียน middleware ที่ wrap ทุก request FastAPI มีแนวคิดเดียวกัน: @app.middleware("http") ตกแต่ง async function ที่รับ request และ callable ชื่อ call_next ซึ่งเรียก layer ถัดไปเหมือนการเรียก next() ใน Express
// Express middlewareapp.use((req, res, next) => { const start = Date.now(); res.on('finish', () => { const ms = Date.now() - start; console.log(`${req.method} ${req.url} ${res.statusCode} ${ms}ms`); }); next();});# FastAPI middlewareimport timefrom fastapi import FastAPI, Request
app = FastAPI()
@app.middleware("http")async def log_requests(request: Request, call_next): start = time.perf_counter() response = await call_next(request) ms = (time.perf_counter() - start) * 1000 print(f"{request.method} {request.url.path} " f"{response.status_code} {ms:.1f}ms") return responseการเพิ่ม custom headers
หัวข้อที่มีชื่อว่า “การเพิ่ม custom headers”Use case ที่พบบ่อยของ middleware คือการ inject headers ทุก response สำหรับ request tracing, caching hints หรือ security policies
// Express — เพิ่ม header ใน middlewareapp.use((req, res, next) => { res.setHeader('X-Request-Id', crypto.randomUUID()); next();});# FastAPI — แก้ไข response ใน middlewareimport uuidfrom fastapi import FastAPI, Request
app = FastAPI()
@app.middleware("http")async def add_request_id(request: Request, call_next): response = await call_next(request) response.headers["X-Request-Id"] = str(uuid.uuid4()) return responseCross-Origin Resource Sharing (CORS) configure ผ่าน CORSMiddleware เทียบเท่ากับ cors npm package ใน Express หรือ CORS option ของ NestJS
// Expressimport cors from 'cors';app.use(cors({ origin: ['https://myapp.com', 'http://localhost:3000'], methods: ['GET', 'POST', 'PUT', 'DELETE'], allowedHeaders: ['Content-Type', 'Authorization'], credentials: true,}));
// NestJSapp.enableCors({ origin: ['https://myapp.com'], credentials: true,});# FastAPI — CORSMiddlewarefrom fastapi import FastAPIfrom fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware( CORSMiddleware, allow_origins=["https://myapp.com", "http://localhost:3000"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"],)Starlette middleware (class-based)
หัวข้อที่มีชื่อว่า “Starlette middleware (class-based)”สำหรับ middleware ที่ใช้ซ้ำได้ คุณยังสามารถใช้ Starlette’s class-based BaseHTTPMiddleware คล้ายกับ NestJS NestMiddleware ที่มี use() method
// NestJS class middleware@Injectable()export class LoggerMiddleware implements NestMiddleware { use(req: Request, res: Response, next: NextFunction) { console.log('Request...', req.method, req.url); next(); }}# FastAPI — Starlette BaseHTTPMiddlewarefrom starlette.middleware.base import BaseHTTPMiddlewarefrom starlette.requests import Requestfrom fastapi import FastAPI
class LoggerMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): print(f"Request: {request.method} {request.url.path}") response = await call_next(request) print(f"Response: {response.status_code}") return response
app = FastAPI()app.add_middleware(LoggerMiddleware)รันที่เครื่องตัวเอง — ต้องการ FastAPI + server Playground ข้ามในบทเรียนนี้: middleware ต้องการ ASGI request lifecycle และไม่สามารถ demonstrate ด้วย plain Python script