如何建立 REST API:設計、安全及部署
要建立 REST API,先列出你的應用程式所管理的資源(例如用戶、訂單、預訂),為每項資源設定網址,例如 /orders 和 /orders/{id},並用 HTTP 方法執行操作:GET 讀取、POST 建立、PATCH 更新、DELETE 刪除。回傳資料使用 JSON,並配上有意義的狀態碼;驗證每項輸入;在伺服器端要求身份驗證及逐筆記錄的權限檢查;清單需要分頁。最後為端點撰寫文件,並把 API 部署在 HTTPS 之後。
本指南涵蓋設計決定、一組示範路由、給 AI 應用程式生成器的提示,以及導致保安漏洞的常見錯誤。如果你對 API 尚不熟悉,可先閱讀什麼是 API。
何時需要 REST API
- 你的網頁前端需要向伺服器儲存及讀取資料
- 手機應用程式、合作夥伴或自動化工具需要存取你的資料
- 其他服務會向你發送事件(webhook)
- 你的前端與後端由不同團隊負責
REST 是最常見的風格,但並非唯一選擇。REST 與 GraphQL一文說明何時單一、靈活的查詢端點會更合適。
先設計:資源與路由
先寫下你的應用程式中的名詞,以及用戶會對它們做什麼操作。以一個簡單的預訂應用程式為例:
| 方法 | 路由 | 作用 | 成功狀態碼 |
|---|---|---|---|
GET | /api/bookings | 列出呼叫者的預訂(分頁) | 200 |
POST | /api/bookings | 建立預訂 | 201 |
GET | /api/bookings/{id} | 取得單一預訂 | 200 |
PATCH | /api/bookings/{id} | 修改部分欄位 | 200 |
DELETE | /api/bookings/{id} | 取消預訂 | 204 |
GET | /api/health | 供監察用的健康檢查 | 200 |
這些對應到建立、讀取、更新及刪除;參見什麼是 CRUD。值得遵循的慣例:
- 網址使用複數名詞,不含動詞:用
/bookings,不用/getBookings。 - 只在有助釐清擁有權時才巢狀一層:例如
/bookings/{id}/notes。 - 非 CRUD 的操作可以作為子資源:
POST /bookings/{id}/cancel比一個含糊的 PATCH 更清楚。 - 欄位命名保持一致,例如所有地方都用
created_at。
狀態碼與錯誤
使用標準 HTTP 狀態碼,讓客戶端無需解析文字也能知道發生了什麼事:
| 狀態碼 | 含義 | 使用時機 |
|---|---|---|
| 200 | OK | 讀取或更新成功 |
| 201 | Created | POST 建立了資源 |
| 204 | No Content | 成功,但無需回傳內容 |
| 400 | Bad Request | 輸入未通過驗證 |
| 401 | Unauthorized | 未登入,或權杖無效 |
| 403 | Forbidden | 已登入,但無權操作 |
| 404 | Not Found | 資源不存在,或呼叫者不應知道它存在 |
| 409 | Conflict | 重複資料,或時段已被預訂 |
| 429 | Too Many Requests | 已觸發速率限制 |
| 500 | Server Error | 你的伺服器出現錯誤 |
錯誤回應應採用一致的 JSON 結構,例如 {"error": {"code": "slot_taken", "message": "該時段已不再可用。"}},並且切勿在回應中包含堆疊追蹤或資料庫錯誤。
選項與取捨
| 決定 | 簡單選擇 | 其他方案 |
|---|---|---|
| API 放在哪裡 | 你的網頁框架內的 API 路由 | 獨立的 API 服務,適合多個客戶端或使用不同語言的情況 |
| 身份驗證 | 自家網頁應用程式用 session cookie | 手機應用程式及第三方使用權杖(bearer token 或 API 金鑰) |
| 分頁 | ?page=2&limit=20 | 游標式(?after=...),對龐大、經常變動的清單較穩定 |
| 版本管理 | 在外部用戶開始依賴之前不設定 | 外部用戶依賴後,在路徑加入 /v1/ |
| 文件 | 列出路由的 README | OpenAPI 規格,工具可據此生成互動式文件及客戶端程式碼 |
逐步建立
- 列出資源與路由,如上所述,包括每條路由可由誰呼叫。
- 建立資料模型:在資料庫中設定你需要的欄位與關聯。
- 先建讀取路由,然後才建建立、更新及刪除。
- 在每次寫入時驗證輸入:使用結構驗證函式庫檢查必填欄位、類型、長度及允許值,並拒絕未知欄位。
- 加入身份驗證,然後是逐筆記錄的授權:讀取
/bookings/42時,必須檢查預訂 42 是否屬於呼叫者,而不只是確認有人已登入。 - 所有清單都要分頁,並設定頁面大小上限。
- 對登入及開銷較大的路由限制速率。參見速率限制。
- 只有在瀏覽器需要從其他網域呼叫 API 時才設定 CORS,並明確列出那些來源。如何修復 CORS 錯誤說明你會遇到的錯誤。
- 為每條路由撰寫文件與測試,包括失敗情況。
- 部署:機密資料放在環境變數中,使用 HTTPS,並設有日誌及健康檢查。
給 AI 應用程式生成器的提示
建立骨架:
為預訂建立一個 REST API,路由如下:GET /api/health、GET /api/bookings(分頁,每頁最多 50 筆)、POST /api/bookings、GET /api/bookings/:id、PATCH /api/bookings/:id、DELETE /api/bookings/:id。資料存放於我們的資料庫。使用結構驗證函式庫驗證請求內容,並拒絕未知欄位。錯誤以 JSON 格式回傳,結構為 {"error": {"code", "message"}},並使用正確的狀態碼(400、401、403、404、409)。機密資料放在環境變數中。
安全:
每條預訂路由都要求登入。在每次讀取、更新及刪除時,於伺服器端檢查該預訂是否屬於目前用戶;若不屬於,回傳 404。切勿接受請求內容中的用戶 ID 或角色。將 POST /api/bookings 限制為每位用戶每分鐘 20 次。在伺服器端記錄錯誤,但不要回傳堆疊追蹤。
文件:
為這些路由撰寫 OpenAPI 描述,以及一份簡短的 README,每條路由附上請求與回應的範例。
測試你的 API
要從前端以外測試,因為攻擊者必然會這樣做:
- 每條路由在輸入有效時,都能回傳所記錄的結構及狀態碼
- 缺少或無效的欄位會回傳 400,並附清晰的訊息
- 每條受保護路由在沒有權杖時都回傳 401
- 用戶 A 以 ID 要求用戶 B 的記錄時,回傳 404 或 403
- 清單已分頁;過大的
limit會被限制 - 重複或衝突的建立請求回傳 409,而不是 500
- 超出速率限制時回傳 429
- 錯誤回應不含堆疊追蹤、SQL 或機密資料
- CORS 只允許你打算允許的來源
常見錯誤
- **只檢查登入,不檢查擁有權。**這是最常見的 API 漏洞:任何已登入的用戶只要更改 ID,就能讀取任何記錄。
- **信任客戶端。**請求內容中的價格、角色及用戶 ID 都可被修改。
- **回傳整行資料庫記錄。**密碼雜湊與內部欄位會外洩。應自行決定每個回應包含哪些內容。
- **不設上限的清單。**一次請求取回所有記錄,可能令整個應用程式變慢。
- **內容中夾帶錯誤訊息卻仍回傳
200 OK。**客戶端及監察工具無法判斷請求已失敗。 - 在使用 cookie 的 API 上把 CORS 設定為允許所有來源。
- 沒有健康檢查或日誌,結果要等用戶投訴才知道服務中斷。
如需更全面的上線前檢視,請參閱AI 建立應用程式的安全清單。
在 Mythex 建立 REST API
你可以要求 Mythex 把 API 作為應用程式的一部分建立,或作為獨立服務。Mythex 文件中的 REST API 後端食譜提供了起始提示:列明你的框架與路由,要求清晰的 JSON 錯誤,把機密資料放在環境變數中,並包含一個 Dockerfile。Node、Python、C#、Java 等容器後端都透過 Dockerfile 發布,Mythex 會從 Publish 處理部署(API 後端)。一個專案可以同時運行網站與 API 伺服器,並可在預覽中切換兩者。把金鑰儲存為專案機密;如果 API 需要資料庫,請在對話中提出要求。如需為 API 安排背景工作,請參閱如何執行背景工作。
常見問題
什麼是 REST API?
REST API 是讓程式透過 HTTP 讀寫你應用程式資料的一種方式。每類資料都是一項資源,擁有自己的網址,例如 /orders,而標準的方法會對它作出操作:GET 用來讀取、POST 用來建立、PATCH 或 PUT 用來更新、DELETE 用來刪除。資料一般以 JSON 格式傳送。
我應該用哪種語言建立 REST API?
選用你或團隊能夠維護的語言即可。Node.js 配 Express 或 Fastify、Python 配 FastAPI,以及 C# 或 Java 的框架都很好用。路由、狀態碼、驗證和身份驗證的設計規則,比語言本身更重要。
如何保護 REST API?
每條非公開路由都要求身份驗證;在伺服器端檢查呼叫者是否有權存取每筆特定記錄;驗證所有輸入;使用 HTTPS;限制請求速率;把機密資料放在環境變數中。切勿信任由客戶端傳來的 ID 或角色。
REST API 是否需要獨立的後端?
不一定。Next.js 等框架可以在提供頁面的同時提供 API 路由。當多個客戶端(網頁、手機應用程式、合作夥伴)會使用同一套 API,或需要自己的語言或擴展方式時,獨立的 API 服務才有意義。