我們將使用 Node.js 建立一個 CRUD(新增、讀取、更新、刪除)的 RESTful API。RESTful API 是現代軟體開發中非常重要的一部分,它提供了一種標準化的方式來訪問和操作資料,並支援各種前端和移動應用。
開發流程
- 建立 Server
- 設置 cors 表頭資訊
- 設置 OPTIONS API
- 404 無對應路由
- 設置 RESTful API (GET、POST、DELETE、PATCH)
1. 建立 Server
新增一個 app.js,透過 createServer 開啟伺服器
app.js
1 2 3 4 5 6 7 8 9
| import http from 'http';
const server = http.createServer((req, res) => { });
server.listen(3000, () => { console.log('Server is running on port 3000'); });
|
2. 設置 cors 表頭資訊
1 2 3 4 5 6 7 8
| const server = http.createServer((req, res) => { const headers = { 'Access-Control-Allow-Headers': 'Content-Type, Authorization, Content-Length, X-Requested-With', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'PATCH, POST, GET, OPTIONS, DELETE', 'Content-Type': 'application/json' } });
|
- Access-Control-Allow-Headers:允許在實際請求中使用特定的請求標頭
- Access-Control-Allow-Origin:允許跨來源的來源,*表示任何來源
- Access-Control-Allow-Methods:允許使用 HTTP Methods
- Content-Type:回傳的內容格式
3. 設置 OPTIONS API
Preflight(預檢)機制
由於網頁與主機的 domain 不同,在某些時機點,call API 時會傳送兩次 request
第一次造訪雲端,Request Method 會是 OPTIONS,確認主機可以造訪
第二次才會是使用者發出的請求(Delete)
*圖片來自六角學院
如果滿足以下任一項條件時會發出預檢請求
- PUT
- DELETE
- CONNECT
- OPTIONS
- TRACE
- PATCH
設定 OPTIONS 條件
1 2 3 4 5 6 7 8 9 10 11 12 13
| const server = http.createServer((req, res) => { const headers = { 'Access-Control-Allow-Headers': 'Content-Type, Authorization, Content-Length, X-Requested-With', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'PATCH, POST, GET, OPTIONS, DELETE', 'Content-Type': 'application/json' }
if(req.method === 'OPTIONS') { res.writeHead(200, headers); res.end(); } });
|
4. 404 無對應路由
1 2 3 4 5 6 7 8 9
| } else { res.writeHead(404, headers); res.write(JSON.stringify({ "status": "false", "message": "無此頁面" })); res.end(); }
|
5. 設置 RESTful API
GET
設置路由與 http method 後,進行回傳
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import http from 'http'; const todos = [];
const server = http.createServer((req, res) => { const headers = ...
if(req.url === '/todos' && req.method === 'GET') { res.writeHead(200, headers); res.write(JSON.stringify({ "status": "success", "data": todos })); res.end(); } else if(req.method === 'OPTIONS') { } else { } });
|
確認請求的路由如果為 ‘/todos’ 且為 GET 時,將會回傳 status code 200,並回傳 JSON 資訊
todos 會是所有資料的集合,目前為空陣列
在 Postman 測試看一下,就會出現我們設定的資訊
POST
在 Node.js 中,當進行 HTTP POST 請求時,資料通常是以 TCP 封包的形式進行傳輸的。當使用者在前端透過瀏覽器提交表單或發送 POST 請求時,資料會被分割成多個小塊(chunks),並以 TCP 封包的方式傳送到伺服器。
當伺服器接收到這些封包時,它並不會立即得到完整的資料。相反,它會持續累加這些封包,直到收到所有封包並組合成完整的資料。這是因為 TCP 封包的傳輸順序不一定與原始資料的順序完全一致,有可能先收到後面的封包再收到前面的封包,因此伺服器需要等待所有封包到達,然後根據每個封包的順序來組合資料,才能得到最終的完整資料。
*圖片來自六角學院
在資料尚未完整組合之前,伺服器通常會將每個封包的內容暫時儲存起來,這種暫存區域稱為緩衝區(buffer)。當所有封包都到達並組合完成後,伺服器會將緩衝區中的資料取出並進行處理,以獲得最終的完整資料。
所以我們會用一個 body 來將 chunk 組起來
1 2 3 4 5 6 7 8
| let body = ''; req.on('data', chunk => { body += chunk; })
req.on('end', () => { console.log(JSON.parse(body).title); })
|
在註冊資料時,用戶提交的表單或 POST 請求中的資料可能會非常龐大,可能會被分割成數個小塊封包。伺服器在接收到這些封包後,會持續累加這些封包,直到收到所有封包並組合成完整的註冊資料。當伺服器確定資料已完整收到時,它就會將這些資料進行處理,例如儲存到資料庫中或進行其他相關處理。
這種方式可以確保資料在傳輸過程中不會丟失或損毀,同時也讓伺服器能夠在收到完整資料後再進行相應的處理,以確保資料的完整性和正確性。
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
| import http from 'http'; import { v4 as uuidv4 } from 'uuid'; import { errHandle } from "./errorHandle.js"; const todos = [];
const server = http.createServer((req, res) => {
let body = ''; req.on('data', chunk => { body += chunk; })
if(req.url === '/todos' && req.method === 'GET') { } else if(req.url === '/todos' && req.method === 'POST') { req.on('end', () => { try { let title = JSON.parse(body).title; if(title !== undefined) { let todo = { title: title, id: uuidv4() }; todos.push(todo); res.writeHead(200, headers); res.write(JSON.stringify({ "status": "success", "data": todos })); res.end(); } else { errHandle(res); } } catch (error) { errHandle(res); } }) } else if { } else { } });
server.listen(3000, () => { console.log('Server is running on port 3000'); });
|
當使用者傳入 title,如果 title 為有效值,將會回傳成功訊息,並回傳唯一性的 id,如錯誤將會執行錯誤處理
為了檔案整潔,另外抽了一支 errorHandle.js 專門處理錯誤訊息
errorHandle.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| export const errHandle= (res) => { const headers = { 'Access-Control-Allow-Headers': 'Content-Type, Authorization, Content-Length, X-Requested-With', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'PATCH, POST, GET,OPTIONS,DELETE', 'Content-Type': 'application/json' } res.writeHead(400, headers); res.write(JSON.stringify({ "status": "false", "message": "欄位未填寫正確,或無此 to id" })); res.end(); }
|
用 Postman 測試,成功將會出現回傳資訊
輸入無效值,將會出現 400 錯誤訊息
DELETE
全部清空
目前 GET /todos 有一筆我們剛剛新增的資料,我們現在要把資料全部清空,作法也很簡單
app.js
1 2 3 4 5 6 7 8 9
| else if(req.url === '/todos' && req.method === 'DELETE') { todos.length = 0; res.writeHead(200, headers); res.write(JSON.stringify({ "status": "success", "data": todos })); res.end(); }
|
將 todos 集合全部清空,並回傳成功訊息
清空單筆
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| else if(req.url.startsWith('/todos/') && req.method === 'DELETE') { const id = req.url.split('/').pop(); const index = todos.findIndex(item => item.id === id); if(index !== -1) { todos.splice(index, 1); res.writeHead(200, headers); res.write(JSON.stringify({ "status": "success", "data": todos, })); res.end(); } else { errHandle(res); } }
|
- startsWith() 用於檢查一個字串是否以指定的字串開頭。這個方法會回傳一個布林值,表示該字串是否以指定的字串開頭
- 找到符合路由的 id 並將該筆資料刪除
將會移除符合 f061bfb2-64da-4949-8230-cd07c3e7137d
此組 id 的資料
PATCH
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| else if(req.url.startsWith('/todos/') && req.method === 'PATCH') { req.on('end', () => { try { let title = JSON.parse(body).title; const id = req.url.split('/').pop(); const index = todos.findIndex(item => item.id === id); if(title !== undefined && index !== -1) { todos[index].title = title; res.writeHead(200, headers); res.write(JSON.stringify({ "status": "success", "data": todos, })); res.end(); } else { errHandle(res); } } catch (error) { errHandle(res); } }) }
|
- 找到符合路由的 id
- 如有符合 id 的資料且 title 的資料為有效就進行修改
🚀實體工作坊分享
最近時賦學苑開了實體體驗課,即使你對程式碼沒有概念也能上手!Lala 會帶你一起做出一個個人品牌形象網站,帶你快速了解前端的開發流程,快跟我們一起玩轉 Web 吧!
🚀線上課程分享
線上課程可以加速學習的時間,省去了不少看文件的時間XD,以下是我推薦的一些課程
想學習更多關於前後端的線上課程,可以參考看看。
Hahow 有各式各樣類型的課程,而且是無限次數觀看,對學生或上班族而言,不用擔心被時間綁住
如果你是初學者,非常推薦六角學院哦!
剛開始轉職也是上了六角的課,非常的淺顯易懂,最重要的是,隨時還有線上的助教幫你解決問題!
Udemy 裡的課程非常的多,品質普遍不錯,且價格都滿實惠的,CP值很高!
也是很多工程師推薦的線上課程網站。