CHAPTER 09 / SERVER SIDE
後端、API、
Python
前端是櫃檯,後端是廚房。客人看不到廚房但沒它出不了菜。 這章從零教你寫後端:Node.js(接前端最順)、Python(資料 / AI 必備)、API 設計、JWT 登入。
- 能寫 Node.js / Python 後端 API
- 會設計 RESTful API
- 會做使用者註冊登入(JWT)
- 會處理檔案上傳、CORS、錯誤
- 會看別人的後端程式碼
LESSON 9.1
什麼是後端?
使用者打開 Insight,看到自己發過的問卷。問卷存哪?密碼怎麼比對?這些使用者看不到的東西就是後端。
後端做什麼
- 儲存:使用者資料、文章、訂單
- 運算:金額計算、AI 推論、報表生成
- 授權:誰能看誰的資料
- 整合:接金流、寄信、推播
後端語言怎麼挑
| 語言 | 適合 |
|---|---|
| Node.js | 跟前端共用 JS / TS、即時應用 |
| Python | AI / 資料、初學最易 |
| Go | 高效能、雲端基建 |
| Java/Kotlin | 大公司後台、銀行 |
| PHP | WordPress、舊專案 |
學員最該選哪一個?Node.js(前端工程師延伸)+ Python(AI 必備)。這兩個學會走遍天下。Next.js 的 API Routes 已是 Node.js,所以你某種程度已經寫過後端了。
LESSON 9.2
HTTP 與 REST API
API = Application Programming Interface = 別人的服務跟你的程式溝通的窗口。
HTTP 動詞
| 動詞 | 意思 | 範例 |
|---|---|---|
| GET | 讀 | GET /users |
| POST | 新增 | POST /users |
| PUT/PATCH | 更新 | PATCH /users/1 |
| DELETE | 刪除 | DELETE /users/1 |
狀態碼
- 2xx 成功:200 OK、201 Created、204 No Content
- 3xx 重定向:301 永久、302 暫時
- 4xx 客戶端錯:400 Bad Request、401 Unauthorized、403 Forbidden、404 Not Found、429 Too Many
- 5xx 伺服器錯:500 Internal、502 Bad Gateway、503 Service Unavailable
RESTful 設計範例
GET /api/posts 列出文章
GET /api/posts/42 取單篇
POST /api/posts 新增
PATCH /api/posts/42 更新
DELETE /api/posts/42 刪除
GET /api/posts/42/comments 取留言
POST /api/posts/42/comments 新增留言
LESSON 9.3
Node.js + Express
npm init -y
npm install express
npm install -D @types/express tsx typescript
// server.ts
import express from 'express';
const app = express();
app.use(express.json());
// 假資料
let posts = [
{ id: 1, title: '第一篇' }
];
app.get('/api/posts', (req, res) => {
res.json(posts);
});
app.post('/api/posts', (req, res) => {
const post = { id: Date.now(), ...req.body };
posts.push(post);
res.status(201).json(post);
});
app.delete('/api/posts/:id', (req, res) => {
posts = posts.filter(p => p.id !== Number(req.params.id));
res.status(204).end();
});
app.listen(3000, () => console.log('http://localhost:3000'));
Hono:現代輕量替代
// 比 Express 快、TS 友善、可跑在 Cloudflare Workers
import { Hono } from 'hono';
const app = new Hono();
app.get('/api/posts', c => c.json(posts));
export default app;
LESSON 9.4
Python:FastAPI
FastAPI 是 Python 後端首選——快、自動產 API 文件、TS 等級的型別安全。
pip install fastapi uvicorn[standard]
# main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List
app = FastAPI()
class Post(BaseModel):
id: int
title: str
posts: List[Post] = []
@app.get("/api/posts")
def list_posts():
return posts
@app.post("/api/posts", status_code=201)
def create_post(post: Post):
posts.append(post)
return post
@app.delete("/api/posts/{post_id}")
def delete_post(post_id: int):
global posts
posts = [p for p in posts if p.id != post_id]
return {"ok": True}
uvicorn main:app --reload
# 開瀏覽器到 http://localhost:8000/docs 看自動產生的 API 文件!
FastAPI 自動產生 Swagger / ReDoc 文件。你寫好 API 直接給前端說「看 /docs」,溝通成本砍半。
LESSON 9.5
使用者註冊 / 登入(JWT)
密碼存法(重要)
import bcrypt from 'bcrypt';
// 註冊:存 hash 而不是明碼!
const hash = await bcrypt.hash(plainPassword, 10);
await db.users.create({ email, password: hash });
// 登入:比對
const user = await db.users.findOne({ email });
const ok = await bcrypt.compare(plainPassword, user.password);
if (!ok) throw new Error('帳密錯誤');
密碼絕對不能存明碼。就算自己網站,資料庫一外洩使用者一輩子的密碼通通暴露,他們可能在別的網站用同個密碼。一定要 bcrypt / argon2 雜湊。
JWT
import jwt from 'jsonwebtoken';
// 簽 token
const token = jwt.sign(
{ userId: user.id },
process.env.JWT_SECRET!,
{ expiresIn: '7d' }
);
// 驗 token(middleware)
function auth(req, res, next) {
const token = req.headers.authorization?.replace('Bearer ', '');
try {
req.user = jwt.verify(token, process.env.JWT_SECRET!);
next();
} catch {
res.status(401).json({ error: 'Invalid' });
}
}
JWT 存哪?localStorage 容易被 XSS 偷。建議用 httpOnly cookie。詳細見第 13 章。
LESSON 9.6
CORS、檔案上傳、環境變數
// CORS:允許前端網域
import cors from 'cors';
app.use(cors({
origin: ['https://my-site.com'],
credentials: true
}));
// 檔案上傳
import multer from 'multer';
const upload = multer({
dest: 'uploads/',
limits: { fileSize: 5 * 1024 * 1024 }
});
app.post('/upload', upload.single('file'), (req, res) => {
res.json({ filename: req.file.filename });
});
// 環境變數(.env)
// .env
// DATABASE_URL=postgres://...
// JWT_SECRET=xxx
import 'dotenv/config';
process.env.JWT_SECRET;
.env 永遠加進 .gitignore。把密鑰 commit 上 GitHub 是大型事故。GitHub 有 secret scanning 會通知你,但被機器人爬走通常已晚。
練習:留言板 API
用 Express 或 FastAPI 寫:
POST /register註冊(密碼 bcrypt)POST /login簽 JWTGET /messages列出(公開)POST /messages發文(要 JWT)DELETE /messages/:id只能刪自己的- 用 Postman 或 curl 測試完整流程
常見卡關 FAQ
// 後端學員最常問的問題
前端 fetch 後端跳 CORS 錯誤?
後端要設 CORS。Express 用
cors 套件、FastAPI 用 CORSMiddleware。Production 要把 origin 鎖到自己的網域,不要用 *。Express 還是 Fastify 還是 Hono?
Express 最熟、文件最多。Fastify 快兩倍。Hono 最現代、可跑 Edge。新專案我推 Hono + Bun 或 Next.js API Routes。
JWT 還是 Session?
JWT:無狀態、好做微服務、難撤銷。Session:要存 server、好撤銷。中小專案用 Session 或 NextAuth/Auth.js 即可。需要跨 domain / mobile 才上 JWT。
Node 還是 Python?
看用途。一般 web API 用 Node(跟前端共用)。AI、資料處理、寫爬蟲用 Python。兩個都會最強。
怎麼測 API?
Postman、Insomnia、Thunder Client(VS Code 擴充)、curl。FastAPI 內建 Swagger UI。寫測試用 vitest / pytest。