什麼是 RESTful API?怎樣才算是一個『優雅』的 API 設計?

別再把 API 寫成義大利麵了!怎樣才算是一個「優雅」的 RESTful API 設計?
如果你有接手過別人的舊系統(或是幾年前自己寫的 Code),你一定看過這種 API 端點:
/api/get_user_info/api/createNewProject/api/update_post_status_to_published
老實說,這些 API 「能動嗎?」絕對能動。但它們優雅嗎?簡直慘不忍睹。
這就像是一本沒有目錄、章節亂跳的書,前端同事要接你的 API 時,只能通靈或是去翻那份永遠沒在更新的文件。這時候,我們就需要來聊聊業界標準:RESTful API。
🤔 所以,RESTful 到底是什麼玄學?
REST(Representational State Transfer)聽起來很高大上,但白話文就是:「把網路上的所有東西都當作『資源 (Resource)』,然後用標準的動作去操作它。」
它不是一種硬性的程式語言,而是一種「設計風格」與「默契」。當你遵守這個默契,別人光是看你的網址,就知道這支 API 要幹嘛。
要寫出優雅的 RESTful API,只要掌握以下三個核心心法:
心法一:網址是「名詞」,動作交給「HTTP Method」
拜託,不要再把動詞寫進網址裡了!在 RESTful 的世界裡,網址只代表你要操作的「目標(資源)」。
❌ 災難級的設計(動詞塞滿滿):
- 取得所有專案:
GET /api/getAllProjects - 新增一個專案:
POST /api/createProject - 刪除特定專案:
POST /api/deleteProject?id=5
✅ 優雅的設計(看 HTTP Method 就懂):
- 取得所有專案:
GET /api/projects - 新增一個專案:
POST /api/projects - 刪除特定專案:
DELETE /api/projects/5
有沒有發現?網址永遠只有 /api/projects(推薦用複數名詞),我們是透過前端發送的 HTTP Method(GET、POST、PUT、DELETE)來決定要對這個資源做什麼事。這畫面看起來瞬間乾淨了一百倍。
心法二:善用 HTTP 狀態碼 (Status Code),別當「永遠的 200 OK」
這是我最常遇到的雷坑。有些 API 不管發生什麼事,HTTP 狀態碼永遠回傳 200 OK,然後把錯誤訊息包在 JSON 裡面:
❌ 假裝沒事的 API:
// HTTP Status: 200 OK
{
"status": "error",
"message": "找不到該名使用者"
}
這會把前端搞瘋,因為前端的 axios.catch 根本抓不到這個錯誤,還得自己寫 if (res.data.status === 'error') 去判斷。
✅ 優雅的 API 應該這樣給狀態碼:
200 OK:一切順利,拿去吧。201 Created:剛才用POST新增資料成功了!400 Bad Request:前端傳來的格式有錯(例如 Pydantic 驗證失敗)。401 Unauthorized:你誰?你沒給 JWT Token 或是過期了。403 Forbidden:雖然我知道你是誰,但你沒有權限刪除這筆資料。404 Not Found:資源不存在(例如你去GET /api/projects/999,但根本沒這個專案)。500 Internal Server Error:後端自己寫出 Bug 炸了,我的鍋。
善用狀態碼,是一支專業 API 的基本素養。
心法三: PUT 跟 PATCH 到底差在哪?
這題根本是面試必考題。這兩個都是用來「更新」資料,但語意完全不同:
PUT(覆蓋):整筆替換。假設一個使用者有name跟age,你用PUT只傳了name,那後端應該要把他的age變成 null。PATCH(局部更新):打補丁。你傳了name,後端就只更新name,原來的age不受影響。
實務上我們通常比較愛用 PATCH,但很多偷懶的設計會全部混著用 POST 解決。如果有心把架構弄好,把它們分清楚會讓系統邏輯更嚴謹。
🍻 總結:優雅來自於「換位思考」
說到底,為什麼我們要這麼龜毛去遵守 RESTful API 規範?
其實這就是一種 「工程師的同理心」。當你把 API 設計得直覺、網址乾淨、狀態碼精準,負責接 API 的前端同事(或是一個月後接手維護的你自己)就不需要整天通靈或是找人問「欸,這支 API 報錯到底回什麼格式啊?」。
現在像是 FastAPI 這種現代化框架,其實已經在底層不斷引導我們寫出符合 RESTful 精神的架構了。下次開新端點前,不妨停下來想個 10 秒鐘:「我這個網址,取得夠優雅嗎?」
大家專案開發順利,我們下篇文章見!
