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