Routing และ Parameters
Route decorators vs app.get()
หัวข้อที่มีชื่อว่า “Route decorators vs app.get()”ใน Express คุณเรียก app.get(path, handler) ใน FastAPI คุณตกแต่งฟังก์ชันด้วย @app.get(path) decorator นี้จะลงทะเบียนฟังก์ชันเป็น handler สำหรับ HTTP method + path combination นั้น ฟังก์ชันจะเป็น async def หรือ plain def ก็ได้
// Expressconst app = express();
app.get('/items', (req, res) => { res.json([{ id: 1, name: 'Widget' }]);});
app.post('/items', (req, res) => { const body = req.body; // parse เอง res.status(201).json(body);});# FastAPIfrom fastapi import FastAPI
app = FastAPI()
@app.get("/items")async def list_items(): return [{"id": 1, "name": "Widget"}]
@app.post("/items", status_code=201)async def create_item(item: dict): return itemFastAPI รองรับ HTTP methods มาตรฐานทั้งหมด: @app.get, @app.post, @app.put, @app.patch, @app.delete, @app.options
Path parameters
หัวข้อที่มีชื่อว่า “Path parameters”ครอบชื่อ parameter ด้วยวงเล็บปีกกาใน path string แล้วเพิ่ม argument ที่มี type ตรงกันในฟังก์ชัน FastAPI จะแปลงค่าให้และส่งคืน 422 Unprocessable Entity อัตโนมัติถ้าการแปลงล้มเหลว
// Express — ทุกอย่างเป็น string, แปลงเองapp.get('/items/:id', (req, res) => { const id = parseInt(req.params.id, 10); if (isNaN(id)) return res.status(422).json({ error: 'id must be integer' }); res.json({ id, name: 'Widget' });});
// NestJS@Get(':id')findOne(@Param('id', ParseIntPipe) id: number) { return { id, name: 'Widget' };}# FastAPI — type hint แปลง + validationfrom fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")async def get_item(item_id: int): # GET /items/abc → 422 อัตโนมัติ return {"id": item_id, "name": "Widget"}
# Path params หลายตัว@app.get("/users/{user_id}/items/{item_id}")async def get_user_item(user_id: int, item_id: int): return {"user_id": user_id, "item_id": item_id}Query parameters
หัวข้อที่มีชื่อว่า “Query parameters”argument ของฟังก์ชันตัวไหนที่ไม่ปรากฏใน path string FastAPI จะนับเป็น query parameter ให้อัตโนมัติ ถ้าอยากให้เป็น optional ก็ใส่ค่า default ไว้
// Expressapp.get('/items', (req, res) => { const skip = Number(req.query.skip) || 0; const limit = Number(req.query.limit) || 10; const q = req.query.q as string | undefined; res.json({ skip, limit, q });});# FastAPI — query params จาก function signaturefrom fastapi import FastAPIfrom typing import Optional
app = FastAPI()
@app.get("/items")async def search_items( skip: int = 0, # GET /items?skip=5 limit: int = 10, # GET /items?limit=20 q: Optional[str] = None, # GET /items?q=widget): return {"skip": skip, "limit": limit, "q": q}ลองเล่น — routing logic แบบ plain dict
หัวข้อที่มีชื่อว่า “ลองเล่น — routing logic แบบ plain dict”browser ไม่สามารถรัน HTTP server จริงได้ แต่สามารถสำรวจวิธีที่ FastAPI จับคู่ handler ด้วย plain dict:
# Route registry — สะท้อนวิธีที่ FastAPI map handlersroutes = { ("GET", "/items"): "list_items", ("POST", "/items"): "create_item", ("GET", "/items/{id}"): "get_item", ("PUT", "/items/{id}"): "update_item", ("DELETE", "/items/{id}"): "delete_item",}
def match_route(method: str, path: str) -> str: # ตรงทั้งหมดก่อน key = (method, path) if key in routes: return routes[key] # template match (แบบง่าย) for (m, tmpl), handler in routes.items(): if m != method: continue parts_tmpl = tmpl.split("/") parts_path = path.split("/") if len(parts_tmpl) != len(parts_path): continue if all(t.startswith("{") or t == p for t, p in zip(parts_tmpl, parts_path)): return handler return "404 Not Found"
tests = [ ("GET", "/items"), ("POST", "/items"), ("GET", "/items/42"), ("DELETE", "/items/99"), ("GET", "/unknown"),]for method, path in tests: print(f"{method:6s} {path:20s} -> {match_route(method, path)}")Loading Python runtime (first run only)…