建立 REST API#

REST(Representational State Transfer)是一種 Web API 的設計風格,以 HTTP 方法對應 CRUD 操作,透過 URL 表示資源。本章結合 Express 建立一個完整的 REST API 範例。


1. REST API 設計原則#

HTTP 方法URL操作
GET/users取得所有使用者
GET/users/:id取得特定使用者
POST/users新增使用者
PUT/users/:id更新使用者(完整更新)
PATCH/users/:id更新使用者(部分更新)
DELETE/users/:id刪除使用者

2. 完整範例#

以下建立一個以記憶體陣列儲存資料的使用者 API:

app.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
const express = require("express");
const app = express();

app.use(express.json());

// 模擬資料庫
let users = [
    { id: 1, name: "Alice", email: "alice@example.com" },
    { id: 2, name: "Bob", email: "bob@example.com" },
];
let nextId = 3;

// GET /users - 取得所有使用者
app.get("/users", (req, res) => {
    res.json(users);
});

// GET /users/:id - 取得特定使用者
app.get("/users/:id", (req, res) => {
    const id = parseInt(req.params.id);
    const user = users.find((u) => u.id === id);

    if (!user) {
        return res.status(404).json({ error: "找不到使用者" });
    }

    res.json(user);
});

// POST /users - 新增使用者
app.post("/users", (req, res) => {
    const { name, email } = req.body;

    if (!name || !email) {
        return res.status(400).json({ error: "name 和 email 為必填欄位" });
    }

    const newUser = { id: nextId++, name, email };
    users.push(newUser);

    res.status(201).json(newUser);
});

// PUT /users/:id - 更新使用者
app.put("/users/:id", (req, res) => {
    const id = parseInt(req.params.id);
    const index = users.findIndex((u) => u.id === id);

    if (index === -1) {
        return res.status(404).json({ error: "找不到使用者" });
    }

    const { name, email } = req.body;
    if (!name || !email) {
        return res.status(400).json({ error: "name 和 email 為必填欄位" });
    }

    users[index] = { id, name, email };
    res.json(users[index]);
});

// PATCH /users/:id - 部分更新使用者
app.patch("/users/:id", (req, res) => {
    const id = parseInt(req.params.id);
    const user = users.find((u) => u.id === id);

    if (!user) {
        return res.status(404).json({ error: "找不到使用者" });
    }

    Object.assign(user, req.body);
    res.json(user);
});

// DELETE /users/:id - 刪除使用者
app.delete("/users/:id", (req, res) => {
    const id = parseInt(req.params.id);
    const index = users.findIndex((u) => u.id === id);

    if (index === -1) {
        return res.status(404).json({ error: "找不到使用者" });
    }

    users.splice(index, 1);
    res.status(204).send(); // 204 No Content
});

app.listen(3000, () => {
    console.log("API 伺服器啟動於 http://localhost:3000");
});

3. 測試 API#

可以使用 curl 測試:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 取得所有使用者
curl http://localhost:3000/users

# 取得特定使用者
curl http://localhost:3000/users/1

# 新增使用者
curl -X POST http://localhost:3000/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Carol","email":"carol@example.com"}'

# 更新使用者
curl -X PUT http://localhost:3000/users/1 \
  -H "Content-Type: application/json" \
  -d '{"name":"Alice Updated","email":"alice@example.com"}'

# 刪除使用者
curl -X DELETE http://localhost:3000/users/1

也可以使用 Postman 或 VS Code 的 REST Client 擴充套件進行測試。


4. 專案結構建議#

隨著 API 越來越複雜,建議按照以下結構組織程式碼:

my-api/
├── app.js              # Express 應用程式設定
├── server.js           # 啟動伺服器
├── routes/
│   └── users.js        # 路由定義
├── controllers/
│   └── userController.js  # 業務邏輯
└── package.json

5. 小結#

本章完成了一個基本的 CRUD REST API。下一步可以學習:

  • 連接真正的資料庫(如 MongoDB、PostgreSQL)
  • 加入身份驗證(JWT)
  • 加入資料驗證(如 zodjoi
  • 部署到雲端(如 Render、Fly.io)

Reference#