[Node.JS] 打造 todolist api 2 - 撰寫程式基本架構

前一篇整理的資訊中共有 5 種請求方法和延伸的處理結果需要撰寫,在這篇文章中就要建立這些功能的結構。


💎 基礎 route 撰寫

前面練習的網址都是使用根目錄(/),在網址加上一個路徑名稱才能方便辨識這個 api 的用途,方法很簡單,加入一個 if…else 來判斷 req.url 即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const server = http.createServer((req, res) => {
// 比對請求的網址後名的路徑是不是設定好的字串
if (req.url == '/todo') {
res.writeHead(200, headers);
// 調整回傳的內容
res.write(JSON.stringify({
"status": "true"
}));
res.end();
} else {
// 不符合路徑就傳 404 錯誤
res.writeHead(404, headers);
// 調整回傳的內容
res.write(JSON.stringify({
"status": "false"
}));
res.end();
}
});

段落測試:使用瀏覽器連 http://127.0.0.1:3000http://127.0.0.1:3000/todo 查看是否有不同結果。


💎 建立回應函式

前一個步驟中加入了第一個判斷,就可以發現 res 有許多程式碼重複,後續還有各種方法的判斷,可以先把它抽出來寫成函式避免後續產生大量重複程式碼。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const sendResponse = (res, statusCode, data) => {
res.writeHead(statusCode, headers);
res.write(JSON.stringify(data));
res.end();
};

const server = http.createServer((req, res) => {
if (req.url == '/todo') {
sendResponse(res, 200, {
"status": "true"
});
} else {
sendResponse(res, 404, {
"status": "false"
});
}
});

段落測試:使用瀏覽器連 http://127.0.0.1:3000http://127.0.0.1:3000/todo 查看是否運作正常。


💎 判斷各種連線方法

用來判別各種狀況的基本寫法是 if...elseswitch...case,這部份的判斷方式因人而異,可以自行思考設計,以下個人的寫法僅供參考,也歡迎大家提出改善建議。

🚩 OPTIONS

本次練習中提供了 5 種連線方法,其中 OPTIONS 較為特別,這個方法像是打招呼一樣,只需要回傳 狀態碼headers 即可(就像互相問候,不用說具體的內容),可以放在判斷條件的第一條處理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const sendResponse = (statusCode, data) => {
res.writeHead(statusCode, headers);
// 增加判斷,有資料時才回傳
if (data) {
res.write(JSON.stringify(data));
}
res.end();
};
const server = http.createServer((req, res) => {
// 修改成使用變數
if (req.method == 'OPTIONS') {
sendResponse(res, 200);
} else if (req.url == '/todo') {
sendResponse(res, 200, {
"status": "true"
});
} else {
sendResponse(res, 404, {
"status": "false"
});
}
});

💡💡 重要 💡💡
段落測試:此處開始(包含後續的步驟)需要使用 POSTMAN 軟體來模擬各種連線方法測試。
測試內容:方法 OPTIONS、網址 http://127.0.0.1:3000(後方可加任意字串來測試不同的回應)
參考資料是 Ray 不是 Array - POSTMAN 教學

🚩 其他方法

先把其他會用到的方法加到程式碼中,再針對每個項目補完功能,此處我使用的是 switch…case,也可以 elseif 到底。

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
const server = http.createServer((req, res) => {
if (req.method == 'OPTIONS') {
sendResponse(res, 200);
} else if (req.url == '/todo') {
// 新增各種方法的判斷,並稍微調整回傳內容來測試
switch (req.method) {
case 'GET':
sendResponse(res, 200, {
"status": "true",
"method": "GET"
});
break;
case 'POST':
sendResponse(res, 200, {
"status": "true",
"method": "POST"
});
break;
case 'PATCH':
sendResponse(res, 200, {
"status": "true",
"method": "PATCH"
});
break;
case 'DELETE':
sendResponse(res, 200, {
"status": "true",
"method": "DELETE"
});
break;
// 不符合這些請求方式就回傳錯誤碼
default:
sendResponse(res, 405, {
"status": "false"
});
break;
}
} else {
sendResponse(res, 404, {
"status": "false"
});
}
});

段落測試
測試網址http://127.0.0.1:3000/todo
測試方法:GET、POST、PATCH、DELETE(使用 POSTMAN)

🚩 修改、刪除指定資料

指定資料的修改(PATCH)、刪除(DELETE)在設計上會使用 http://網域/路徑/參數 (例如:http://127.0.0.1:3000/todo/abcd12345) 這個格式的網址,在參數內帶入指定資料的 ID,這時候就無法使用 req.url == '/todo' 來比對(結果會是 false),需要分開判斷。

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
const server = http.createServer((req, res) => {
if (req.method == 'OPTIONS') {
sendResponse(res, 200);
} else if (req.url == '/todo') {
switch (req.method) {
case 'GET':
sendResponse(res, 200, {
"status": "true",
"method": "GET"
});
break;
case 'POST':
sendResponse(res, 200, {
"status": "true",
"method": "POST"
});
break;
/* PATCH 方法調整到下一個判斷 */
// case 'PATCH':
// sendResponse(res, 200, {
// "status": "true",
// "method": "PATCH"
// });
// break;

// DELETE 方法有兩種操作(單筆或全部),這邊保留的用來刪除全部(不需要ID)
case 'DELETE':
sendResponse(res, 200, {
"status": "true",
"method": "DELETE"
});
break;
// 不符合這些請求方式就回傳錯誤碼
default:
sendResponse(res, 405, {
"status": "false"
});
break;
}
// 使用 startsWith 方法來比對路徑開頭
} else if (req.url.startsWith('/todo/')) {
// 修改單筆資料
if (req.method == 'PATCH') {
sendResponse(res, 200, {
"status": "true",
"method": "PATCH + id"
});
// 刪除單筆資料
} else if (req.method == 'DELETE') {
sendResponse(res, 200, {
"status": "true",
"method": "DELETE + id"
});
// 不符合上述兩種方法時回應錯誤
} else {
sendResponse(res, 405, {
"status": "false"
});
}
} else {
sendResponse(res, 404, {
"status": "false"
});
}
});

段落測試
測試網址http://127.0.0.1:3000/todo/(任一字串)
測試方法:PATCH、DELETE(使用 POSTMAN)


💎 結語

本篇的筆記已經完成所有方法的架構,下一篇完結篇就會補上所有的功能。