摘要:要對進行黑盒測試測試的最好辦法是對他們進行黑盒測試,黑盒測試是一種不關心應用內(nèi)部結構和工作原理的測試方法,測試時系統(tǒng)任何部分都不應該被。此外,有了黑盒測試并不意味著不需要單元測試,針對的單元測試還是需要編寫的。
本文首發(fā)于之乎專欄前端周刊,全文共 6953 字,讀完需 8 分鐘,速度需 2 分鐘。翻譯自:RingStack 的文章 https://blog.risingstack.com/10-best-practices-for-writing-node-js-rest-apis/,英文好的同學可以直接閱讀原文,譯文較原文有刪節(jié)。
Node.js 除了用來編寫 WEB 應用之外,還可以用來編寫 API 服務,我們在本文中會介紹編寫 Node.js Rest API 的最佳實踐,包括如何命名路由、進行認證和測試等話題,內(nèi)容摘要如下:
1. 正確使用 HTTP Method 和路由正確使用 HTTP Method 和路由
正確的使用 HTTP 狀態(tài)碼
使用 HTTP Header 來發(fā)送元數(shù)據(jù)
為 REST API 挑選合適的框架
要對 API 進行黑盒測試
使用基于 JWT 的無狀態(tài)的認證機制
學會使用條件請求機制
擁抱接口調(diào)用頻率限制(Rate-Limiting)
編寫良好的 API 文檔
對 API 技術演化保持關注
試想你正要構建一個 API 用來創(chuàng)建、更新、獲取、刪除用戶,對于這些操作,HTTP 規(guī)范里面已經(jīng)有了現(xiàn)成的操作:POST、PUT、GET、DELETE,建議直接使用他們來描述接口的行為。
至于路由的命名,應該使用名詞或名詞性短語來作為資源標識符,比如上文提到的用戶管理的例子,路由就應該長這樣:
POST /users 或者 PUT /users/:id 用來創(chuàng)建新用戶;
GET /users 用來獲取用戶列表;
GET /users/:id 用來獲取單個用戶;
PATCH /users/:id 用來更新用戶信息;
DELETE /users/:id 用來刪除用戶;
2. 正確的使用 HTTP 狀態(tài)碼如果服務器端在請求處理的過程中出錯了,你必須設置正確的響應狀態(tài)碼,具體如下:
2xx,表示一切正常;
3xx,表示資源位置已經(jīng)更改;
4xx,表示因為客戶端錯誤而導致請求無法被處理,比如參數(shù)校驗沒通過;
5xx,表示因為服務器錯誤導致請求無法被處理,比如服務端拋了異常;
如果你使用 express,設置狀態(tài)碼非常簡單:res.status(500).send({ error: "Internal server error happend" }),如果使用了 restify,也是類似的:res.status(201)。
如果想看完整的 HTTP 狀態(tài)碼,點擊這里。
3. 使用 HTTP Header 來發(fā)送元數(shù)據(jù)如果想要發(fā)送關于響應體數(shù)據(jù)的元數(shù)據(jù),可以使用 Header ,Header 可以包含的常見元數(shù)據(jù)包括如下幾類:
分頁信息;
頻率限制信息;
認證信息;
如果你需要在 Header 中發(fā)送自定義的元數(shù)據(jù),最好的做法是在 Header 名稱前面加 X,例如,需要發(fā)送 CSRF Token 的時候,實際的 Header 應該命名為:X-CSRF-Token,然而,這種 Header 在 RFC 6648 中已經(jīng)被廢棄了。API 在設置自定義 Header 的時候還要盡可能避免命名沖突,比如為了達到這個目的OpenStack 為所有 API 的自定義 Header 都加上了 OpenStack 的前綴:
OpenStack-Identity-Account-ID OpenStack-Networking-Host-Name OpenStack-Object-Storage-Policy
需要注意的是,雖然 HTTP 規(guī)范中沒有規(guī)定 Header 的大小,但是 Node.js 中 Header 的大小被限制在了 80KB。官方原文如下:
4. 為 REST API 挑選合適的框架不要讓 HTTP Header ,包括其中狀態(tài)碼那行的整體大小超過 HTTP_MAX_Header_SIZE,這樣做的目的是為了防御基于 Header 的 DDOS 攻擊。點擊這里
根據(jù)你的實際場景挑選合適的框架是非常重要的,Node.js 中的框架大致介紹如下:
Express、Koa、HAPIExpress、Koa、HAPI 主要是用來構建瀏覽器 WEB 應用,因為他們都支持服務端模板渲染,雖然這只是他們眾多功能中的一個。如果你的應用需要提供用戶界面,那么這三個就是不錯的選擇。
Restify而 Restify 是專門用來創(chuàng)建符合 REST 規(guī)范的服務的,他誕生的目的就是幫你構建嚴格意義上的、可維護的 API 服務。Restify 內(nèi)置了所有請求處理函數(shù)的 DTrace 支持。并且已經(jīng)被 npm 和 netflix 用來在生產(chǎn)環(huán)境提供重要的服務。
5. 要對 API 進行黑盒測試測試 API 的最好辦法是對他們進行黑盒測試,黑盒測試是一種不關心應用內(nèi)部結構和工作原理的測試方法,測試時系統(tǒng)任何部分都不應該被 mock。
supertest 是可以用來對接口進行黑盒測試的模塊之一,下面是基于測試框架 mocha 編寫的一個測試用例,該用例的目的是檢查接口是否能返回單條的用戶數(shù)據(jù):
const request = require("supertest") describe("GET /user/:id", function() { it("returns a user", function() { // newer mocha versions accepts promises as well return request(app) .get("/user") .set("Accept", "application/json") .expect(200, { id: "1", name: "John Math" }, done); }); });
可能有人會問:API 服務所連接的數(shù)據(jù)庫里面的數(shù)據(jù)是如何寫進去的呢?
通常來說,你寫測試的時候,要盡可能不對系統(tǒng)狀態(tài)做假設,然而在某些場景下,你需要準確的知道系統(tǒng)當前所處的狀態(tài)以增加更多的斷言來提高測試覆蓋率。如果你有這種需求,你可以試用如下的方法對數(shù)據(jù)庫進行預填充:
選擇生產(chǎn)環(huán)境數(shù)據(jù)的子集來運行黑盒測試;
運行黑盒測試之前把手工構造的數(shù)據(jù)填充到數(shù)據(jù)庫中。
此外,有了黑盒測試并不意味著不需要單元測試,針對 API 的單元測試還是需要編寫的。
6. 使用基于 JWT 的無狀態(tài)的認證機制因為 Rest API 必須是無狀態(tài)的,因此認證機制也需要是無狀態(tài)的,而基于 JWT(JSON Web Token) 的認證機制是無狀態(tài)認證機制中的最佳解決方案。
JWT 的認證機制包含三部分:
Header:包含 token 的類型和哈希算法;
payload:包含聲明信息;
signature:JWT 實際上并不是對 payload 進行加密,只是對其做了簽名;
為 API 添加基于 JWT 的認證機制也非常的簡單,比如下面的代碼:
const koa = require("koa"); const jwt = require("koa-jwt"); const app = koa(); app.use(jwt( secret: "very-secret" })); // Protected middleware app.use(function*() // content of the token will be available on this.state.user this.body = { secret: "42" } });
有了如上的代碼,你的 API 就有了 JWT 的保護。如果要訪問這種被保護的接口,需要使用 Authorization Header 來提供 token,比如:
curl --Header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" my-website.com
你可能注意到了,JWT 模塊并不依賴任何數(shù)據(jù)存儲層,這是因為 token 本身是可以多帶帶被校驗的,token 里面的 payload 甚至可以包含 token 的簽名時間、有效期限。
此外,你還需要確保,所有的 API 接口只能通過更安全的 HTTPS 鏈接來訪問。
7. 學會使用條件請求機制條件請求機制是基于不同的 Header 表現(xiàn)出不同的行為的機制,可以認為這些 Header 就是請求處理方式的先決條件,如果條件滿足,請求處理方式就會有所不同。
可以利用這些 Header 檢測服務器上的資源版本是否匹配特定的資源版本,這些 Header 的取值可以是如下的內(nèi)容:
資源的最后修改時間;
資源的標簽(隨資源變化而變化);
具體來說:
Last-Modified:標識資源的最新修改時間;
Etag:標識資源的標簽;
If-Modified-Since:結合 Last-Modified Header 使用;
If-Non-Match:結合 Etag 使用;
下面來看一個實際的例子:
客戶端不知道 doc 資源的任何版本,所以請求時即不能提供 If-Modified-Since,也不能提供 If-Non-Match 兩個 Header,然后服務端在響應中會增加 Etag 和 Last-Modified 兩個 Header。
接下來,客戶端再次請求相同的資源的時候,就可以帶上 If-Modified-Since 和 If-Non-Match 這兩個 Header 了,然后如果服務器端會檢查資源是否修改,如果沒有修改,直接返回 304 - Not Modified 狀態(tài)碼,而不重復發(fā)送資源的內(nèi)容。
8. 擁抱接口調(diào)用頻率限制(Rate-Limiting)頻率限制是用來控制調(diào)用方有對接口發(fā)起請求的次數(shù),為了讓你的 API 用戶知道他們還剩下多少余額,可以設置下面的 Header:
X-Rate-Limit-Limit:特定時間段內(nèi)允許的最多請求次數(shù);
X-Rate-Limit-Remaining:特定時間段內(nèi)剩余的請求次數(shù);
X-Rate-Limit-Reset:什么時候請求頻率限制次數(shù)會重置;
大多數(shù)的 WEB 框架都支持上面這些 Header,如果內(nèi)置不支持,也可以找到插件來支持,比如,如果你使用了 koa,可以使用 koa-rate-limit。
需要注意的是,不同的 API 服務提供商頻率限制的時間窗差異會很大,比如 GitHub 是 60 分鐘,而 Twitter 是 15 分鐘。
9. 編寫良好的 API 文檔編寫 API 的目的當然是讓別人使用并受益,提供良好的接口文檔至關重要。下面這兩個開源項目可以幫你創(chuàng)建 API 文檔:
API Blueprint
Swagger
如果你愿意使用第三方文檔服務商,可以考慮 Apiary。
10. 對 API 技術演化保持關注過去幾年中,API 技術方案領域出現(xiàn)了兩種新的查詢語言,分別是 Facebook 的 GraphQL 和 Netflix 的 Falcor,為什么需要他們呢?
試想這種 API 接口請求:/org/1/space/2/docs/1/collaborators?include=email&page=1&limit=10,類似的情況會讓 API 很快失控,如果你希望所有接口能返回類似的響應格式,那么 GraphQL 和 Falcor 就能幫你解決這個問題。
關于 GraphQL:
GraphQL 是一種用于 API 的查詢語言,也是一種基于現(xiàn)有數(shù)據(jù)處理數(shù)據(jù)查詢的運行時。GraphQL 為您的 API 中的數(shù)據(jù)提供了一個完整和可理解的描述,使用戶能夠準確地詢問他們需要什么,使得隨著時間推移的 API 演化更容易,GraphQL 還有強大的開發(fā)工具支持。 到這里閱讀更多。
關于 Falcor:
能帶來靈感的優(yōu)秀 API 設計Falcor 是支撐著 Netflix UI 的創(chuàng)新數(shù)據(jù)平臺。Falcor 允許你將所有后端數(shù)據(jù)建模為 Node.js 服務商的單個虛擬 JSON 對象。在客戶端可以使用熟悉的 JavaScript 操作、處理遠程JSON對象。如果你知道你的數(shù)據(jù),你就知道你的 API 長啥樣。 到這里閱讀更多。
如果你正在開發(fā) Rest API 或者準備改進老版本的 API,這里收集了幾個在線上提供服務、設計優(yōu)秀并且非常直接借鑒的 API:
GitHub API
Twilio API
Stripe API
Digital Ocean API
希望讀到這里的同學對如何用 Node.js 編寫良好的 API 有更好的理解,如果有建議,歡迎評論中提出。
One More Thing想直接在微信中訂閱前端周刊?掃下方二維碼關注前端周刊訂閱號。
想和我面對面交流?掃下方二維碼添加我為好友。
Happy Hacking
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/81860.html
摘要:簡評之前,后端開發(fā)路線圖僅僅是一個技術推薦,且沒有明確的方向指明應該遵循的順序,這份重新制作的指南將會給你一個更好的方向。現(xiàn)在開始創(chuàng)建一個包并分發(fā)給其他人使用,并確保遵循迄今為止學到的標準和最佳實踐。 簡評:之前,后端開發(fā)路線圖僅僅是一個技術推薦,且沒有明確的方向指明應該遵循的順序,這份重新制作的指南將會給你一個更好的方向。 現(xiàn)在的 Web 開發(fā)與幾年前完全不同了,有很多不同的東西可以...
摘要:現(xiàn)在開始創(chuàng)建一個包并分發(fā)給其他人使用,并確保遵循你迄今為止學到的標準和最佳實踐。第步實踐對于練習,繼續(xù)編寫單元測試,以完成目前為止所做的實際任務,特別是你在步驟中所做的練習。 今天的Web開發(fā)與幾年前完全不同,有很多不同的東西可以很容易地阻止任何人進入Web開發(fā)。這是我們決定制作這些循序漸進的視覺指南的原因之一,這些指南展示了更大的圖景,并讓任何人清楚了解他們在網(wǎng)頁開發(fā)中扮演的角色。 ...
摘要:異步最佳實踐避免回調(diào)地獄前端掘金本文涵蓋了處理異步操作的一些工具和技術和異步函數(shù)。 Nodejs 連接各種數(shù)據(jù)庫集合例子 - 后端 - 掘金Cassandra Module: cassandra-driver Installation ... 編寫 Node.js Rest API 的 10 個最佳實踐 - 前端 - 掘金全文共 6953 字,讀完需 8 分鐘,速讀需 2 分鐘。翻譯自...
摘要:詳情行人臉識別庫是僅行代碼的人臉識別庫,最小只有。詳情開發(fā)大型應用這是根據(jù)上發(fā)表的演講整理的文章,分享了作者在開發(fā)大型應用后的一些心得。詳情每周一同步更新到歡迎 1. Node.js 10 將帶來什么? Node.js 10 的第一個版本將于本周二(4 月 24 日)發(fā)布,并將在 10 月份推出 LTS 版本,將帶來哪些更新? N-API,持續(xù) HTTP/2 支持,ECMAScript...
摘要:詳情行人臉識別庫是僅行代碼的人臉識別庫,最小只有。詳情開發(fā)大型應用這是根據(jù)上發(fā)表的演講整理的文章,分享了作者在開發(fā)大型應用后的一些心得。詳情每周一同步更新到歡迎 1. Node.js 10 將帶來什么? Node.js 10 的第一個版本將于本周二(4 月 24 日)發(fā)布,并將在 10 月份推出 LTS 版本,將帶來哪些更新? N-API,持續(xù) HTTP/2 支持,ECMAScript...
閱讀 1241·2023-04-25 15:53
閱讀 2110·2021-11-19 09:40
閱讀 3501·2021-10-11 10:59
閱讀 2077·2019-08-30 15:55
閱讀 1965·2019-08-30 15:54
閱讀 2312·2019-08-29 13:03
閱讀 2764·2019-08-28 18:17
閱讀 1518·2019-08-27 10:51