
使用這些基本 REST API 最佳實踐構建出色的 API
const app = express ();
這將為我們的服務奠定基礎,并以 Express 作為我們的框架。接下來,我們需要告訴應用程序我們正在使用一些關鍵部分:
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use("/api/users", require("./routes/api/users"));
這段代碼做了一些事情,但它所做的最重要的事情是通過提供數據存儲方法來啟用 POST 和 PUT 請求。 “app.use(express.json());”允許我們的服務處理 JSON 對象,并且“app.use(express.urlencoded({ Extended: false }));”允許我們將數據處理為字符串或數組。
現在我們已經創建了骨架,我們需要實際設置一個監聽端口。為此,請使用以下代碼:
app.listen(3000, () => console.log('Ready'));
此代碼指示我們的服務偵聽端口 3000,并向控制臺記錄“就緒”狀態,這讓我們知道它已準備好處理請求。
雖然我們可以連接到數據庫(有關更多信息,請查看Express 文檔)?,但我們將通過使用本地文件來存儲用戶數據來保持簡單。為此,我們必須首先創建 Users.js 文件。
我們可以使用 mkdir 命令再次執行此操作。使用以下代碼創建該文件:
touch Users.js
這將創建文件供我們編輯。現在我們有了文件,我們需要創建可供其他系統使用的實際數據結構。為此,請使用以下代碼設置數據結構:
const users = [
{
id: 1,
name: "ExampleUser",
email: "exampleuser@website.com"
}
];
有了這個結構,我們可以在末尾添加一個模塊導出,以允許其他項目文件使用這個結構。為此,請將以下代碼附加到 users.js:
module.exports = users;
接下來,我們需要創建路線和端點。為此,我們將創建一個新的目錄文件夾并將其命名為“routes”,然后創建一個名為“api”的子文件夾。這將使我們能夠將所有路由數據存儲在單獨的目錄中,稍微清理一下我們的結構,并明確將來在故障排除期間可能發生故障的位置。您可以在此處使用“mkdir”操作來執行此操作。
在此文件夾中,我們將創建一個名為 users.js 的新 .js 文件。請注意,我們在這里使用了小寫“u” – 記住術語和標準很重要,并且由于我們已經使用“Users”同名存儲解決方案,因此我們使用“users”來定義它的從屬文件,其中包含我們的路線。
在這個文件中,我們需要創建一些邏輯路由。首先,再次聲明我們需要 Express:
const express = require(‘express’)
接下來,我們需要使用以下代碼定義路由器:
const router = express.Router();
為了確保我們的數據路由清晰并以結構化方式提取數據,我們需要一種為每個用戶實體生成唯一 ID 的方法。為此,首先使用 npm 在我們的核心目錄中安裝“uuid”包:
npm install uuid
回到我們的 Users.js 文件,我們可以使用以下命令調用這個“uuid 包”:
const uuid = require("uuid");
接下來,我們需要設置 API 的路徑,以便我們的用戶系統可以正確處理這些數據。我們可以使用以下代碼來執行此操作:
let users = require("../../Users");
現在我們終于可以創建我們的第一個端點了。我們將創建一個 GET 函數來檢索所有用戶數據。我們可以使用以下代碼來做到這一點:
router.get("/", (req, res) => {
res.json(users);
});
這段代碼使用route.get來處理請求,并傳遞系統中存儲的所有當前用戶數據。為了獲取特定的 ID,我們需要為客戶端提供一種傳遞用戶 ID 并檢查內部數據存儲的方法。我們可以使用以下代碼來執行此操作:
router.get("/:id", (req, res) => {
const found = users.some(user => user.id === parseInt(req.params.id));
if (found) {
res.json(users.filter(user => user.id === parseInt(req.params.id)));
} else {
res.sendStatus(400);
}
});
請注意,這里有一個“if”函數,當請求格式錯誤或引用不存在的數據時,它會提供通用錯誤代碼。
創建此路由后,我們現在可以使用以下代碼將其導出以供 API 使用:
module.exports = router;
現在我們有了一個功能性 API,它將根據請求提供用戶數據。整潔的!
從這里,我們可以擴展這些端點以提供各種新功能。 CRUD(即創建、讀取、更新、刪除)是 RESTful API 的關鍵概念,并且應該成為應用程序中的核心功能。我們可以使用以下代碼啟用每個功能。
為了創建用戶數據,我們可以使用 POST:
router.post("/", (req, res) => {
const newUser = {
id: uuid.v4(),
name: req.body.name,
email: req.body.email
};
if (!newUser.name || !newUser.email) {
return res.sendStatus(400);
}
users.push(newUser);
res.json(users);
});
為了更新,我們可以使用 PUT:
router.put("/:id", (req, res) => {
const found = users.some(user => user.id === parseInt(req.params.id));
if (found) {
const updateUser = req.body;
users.forEach(user => {
if (user.id === parseInt(req.params.id)) {
user.name = updateUser.name ? updateUser.name : user.name;
user.email = updateUser.email ? updateUser.email : user.email;
res.json({ msg: "User updated", user });
}
});
} else {
res.sendStatus(400);
}
});
對于刪除,我們可以使用 DELETE:
router.delete("/:id", (req, res) => {
const found = users.some(user => user.id === parseInt(req.params.id))
if (found) {
users = users.filter(user => user.id !== parseInt(req.params.id))
res.json({
msg: "User deleted",
users
});
} else {
res.sendStatus(400);
}
});
這里缺少的一件大事就是 HATEOAS。 HATEOAS(應用程序狀態引擎的超媒體)在我們的用戶數據中提供關系鏈接,是 RESTful 設計的子約束。為了實現這一目標,我們可以使用多種選項——對于我們的例子,我們將使用一個非常簡單的 Express 擴展,稱為“express-hateoas-links”。
首先,首先安裝express-hateoas-links:
npm install express-hateoas-links
安裝完畢后,我們需要開始向我們的“路由”邏輯添加額外的上下文。例如,對于我們的 GET 邏輯,我們將編輯以下內容:
router.get("/:id", (req, res) => {
const found = users.some(user => user.id === parseInt(req.params.id));
if (found) {
res.json(users.filter(user => user.id === parseInt(req.params.id)));
} else {
res.sendStatus(400);
}
});
編輯看起來像這樣:
router.get("/:id", (req, res) => {
const foundUser = users.find(user => user.id === parseInt(req.params.id));
if (foundUser) {
const userWithLinks = {
...foundUser,
links: [
{ rel: "self", method: "GET", href: /users/${foundUser.id}
},
{ rel: "all-users", method: "GET", href: "/users" },
{ rel: "update-user", method: "PUT", href: /users/${foundUser.id}
},
{ rel: "delete-user", method: "DELETE", href: /users/${foundUser.id}
}
]
};
res.json(userWithLinks);
} else {
res.sendStatus(400);
}
});
此更新將添加一些相關鏈接。 “rel”將建立每個上下文鏈接的關系,然后根據用于與原始節點交互的特定方法提供附加上下文鏈接。雖然這些關系鏈接僅用于功能擴展,但也可以通過此方法提供其他關系鏈接,例如有關特定人員的上下文、其組織的鏈接等。
基于最小權限原則在您的服務中實施身份驗證和授權措施至關重要。這種方法涉及將用戶的訪問權限限制在執行任務所需的最低限度。仔細管理對資源的訪問非常重要,確保它們盡可能安全。
謹慎使用超媒體;雖然這可能是有益的,但不加區別地暴露所有資源是不可取的。努力共享有用且??安全的數據,最大限度地減少濫用或泄露的風險。
設計 RESTful API 時,面向資源非常重要。每個資源都應該與執行不同功能的特定 HTTP 動詞相關聯,并且這些交互應該是冪等的(并且安全,盡管這是一個比本文范圍更廣泛的主題)。冪等性意味著每個請求應該一致地產生相同類型的響應,即使實際內容可能有所不同。
為客戶端提供緩存功能是一個關鍵考慮因素,但請確保您的緩存不會緩存可能受到保護或用于攻擊的信息,例如 API 密鑰、用戶數據、登錄方法等。
讓某些東西變得 REST 很容易,但要使其真正 RESTful 可能會有點復雜。通過一些規劃以及基于上下文和關系鏈接的方法,可以非常輕松地開始制作功能強大、可擴展且穩定的 Node.js 應用程序。