自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

編寫(xiě)Node.js Rest API的十個(gè)最佳實(shí)踐

開(kāi)發(fā) 后端
Node.js 除了用來(lái)編寫(xiě) WEB 應(yīng)用之外,還可以用來(lái)編寫(xiě) API 服務(wù),我們?cè)诒疚闹袝?huì)介紹編寫(xiě) Node.js REST API 的最佳實(shí)踐,包括如何命名路由、進(jìn)行認(rèn)證和測(cè)試等話題,內(nèi)容摘要如下:

Node.js 除了用來(lái)編寫(xiě) WEB 應(yīng)用之外,還可以用來(lái)編寫(xiě) API 服務(wù),我們?cè)诒疚闹袝?huì)介紹編寫(xiě) Node.js REST API 的最佳實(shí)踐,包括如何命名路由、進(jìn)行認(rèn)證和測(cè)試等話題,內(nèi)容摘要如下:

  1. 正確使用 HTTP Method 和路由
  2. 正確的使用 HTTP 狀態(tài)碼
  3. 使用 HTTP Header 來(lái)發(fā)送元數(shù)據(jù)
  4. 為 REST API 挑選合適的框架
  5. 要對(duì) API 進(jìn)行黑盒測(cè)試
  6. 使用基于 JWT 的無(wú)狀態(tài)的認(rèn)證機(jī)制
  7. 學(xué)會(huì)使用條件請(qǐng)求機(jī)制
  8. 擁抱接口調(diào)用頻率限制(Rate-Limiting)
  9. 編寫(xiě)良好的 API 文檔
  10. 對(duì) API 技術(shù)演化保持關(guān)注

1. 正確使用 HTTP Method 和路由

試想你正要構(gòu)建一個(gè) API 用來(lái)創(chuàng)建、更新、獲取、刪除用戶,對(duì)于這些操作,HTTP 規(guī)范里面已經(jīng)有了現(xiàn)成的操作:POST、PUT、GET、DELETE,建議直接使用他們來(lái)描述接口的行為。

至于路由的命名,應(yīng)該使用名詞或名詞性短語(yǔ)來(lái)作為資源標(biāo)識(shí)符,比如上文提到的用戶管理的例子,路由就應(yīng)該長(zhǎng)這樣:

  • POST /users 或者 PUT /users/:id 用來(lái)創(chuàng)建新用戶;
  • GET /users 用來(lái)獲取用戶列表;
  • GET /users/:id 用來(lái)獲取單個(gè)用戶;
  • PATCH /users/:id 用來(lái)更新用戶信息;
  • DELETE /users/:id 用來(lái)刪除用戶;

2. 正確的使用 HTTP 狀態(tài)碼

如果服務(wù)器端在請(qǐng)求處理的過(guò)程中出錯(cuò)了,你必須設(shè)置正確的響應(yīng)狀態(tài)碼,具體如下:

  • 2xx,表示一切正常;
  • 3xx,表示資源位置已經(jīng)更改;
  • 4xx,表示因?yàn)榭蛻舳隋e(cuò)誤而導(dǎo)致請(qǐng)求無(wú)法被處理,比如參數(shù)校驗(yàn)沒(méi)通過(guò);
  • 5xx,表示因?yàn)榉?wù)器錯(cuò)誤導(dǎo)致請(qǐng)求無(wú)法被處理,比如服務(wù)端拋了異常;

如果你使用 express,設(shè)置狀態(tài)碼非常簡(jiǎn)單:res.status(500).send({ error: ‘Internal server error happend’ }),如果使用了 restify,也是類(lèi)似的:res.status(201)。

如果想看完整的 HTTP 狀態(tài)碼,點(diǎn)擊這里。

3. 使用 HTTP Header 來(lái)發(fā)送元數(shù)據(jù)

如果想要發(fā)送關(guān)于響應(yīng)體數(shù)據(jù)的元數(shù)據(jù),可以使用 Header ,Header 可以包含的常見(jiàn)元數(shù)據(jù)包括如下幾類(lèi):

  • 分頁(yè)信息;
  • 頻率限制信息;
  • 認(rèn)證信息;

如果你需要在 Header 中發(fā)送自定義的元數(shù)據(jù),最好的做法是在 Header 名稱(chēng)前面加 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ī)范中沒(méi)有規(guī)定 Header 的大小,但是 Node.js 中 Header 的大小被限制在了 80KB。官方原文如下:

不要讓 HTTP Header ,包括其中狀態(tài)碼那行的整體大小超過(guò) HTTP_MAX_Header_SIZE,這樣做的目的是為了防御基于 Header 的 DDOS 攻擊。點(diǎn)擊這里

4. 為 REST API 挑選合適的框架

根據(jù)你的實(shí)際場(chǎng)景挑選合適的框架是非常重要的,Node.js 中的框架大致介紹如下:

Express、Koa、HAPI

Express、Koa、HAPI 主要是用來(lái)構(gòu)建瀏覽器 WEB 應(yīng)用,因?yàn)樗麄兌贾С址?wù)端模板渲染,雖然這只是他們眾多功能中的一個(gè)。如果你的應(yīng)用需要提供用戶界面,那么這三個(gè)就是不錯(cuò)的選擇。

Restify

而 Restify 是專(zhuān)門(mén)用來(lái)創(chuàng)建符合 REST 規(guī)范的服務(wù)的,他誕生的目的就是幫你構(gòu)建嚴(yán)格意義上的、可維護(hù)的 API 服務(wù)。Restify 內(nèi)置了所有請(qǐng)求處理函數(shù)的 DTrace 支持。并且已經(jīng)被 npm 和 netflix 用來(lái)在生產(chǎn)環(huán)境提供重要的服務(wù)。

5. 要對(duì) API 進(jìn)行黑盒測(cè)試

測(cè)試 API 的最好辦法是對(duì)他們進(jìn)行黑盒測(cè)試,黑盒測(cè)試是一種不關(guān)心應(yīng)用內(nèi)部結(jié)構(gòu)和工作原理的測(cè)試方法,測(cè)試時(shí)系統(tǒng)任何部分都不應(yīng)該被 mock。

supertest 是可以用來(lái)對(duì)接口進(jìn)行黑盒測(cè)試的模塊之一,下面是基于測(cè)試框架 mocha 編寫(xiě)的一個(gè)測(cè)試用例,該用例的目的是檢查接口是否能返回單條的用戶數(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);
  });
});

可能有人會(huì)問(wèn):API 服務(wù)所連接的數(shù)據(jù)庫(kù)里面的數(shù)據(jù)是如何寫(xiě)進(jìn)去的呢?

通常來(lái)說(shuō),你寫(xiě)測(cè)試的時(shí)候,要盡可能不對(duì)系統(tǒng)狀態(tài)做假設(shè),然而在某些場(chǎng)景下,你需要準(zhǔn)確的知道系統(tǒng)當(dāng)前所處的狀態(tài)以增加更多的斷言來(lái)提高測(cè)試覆蓋率。如果你有這種需求,你可以試用如下的方法對(duì)數(shù)據(jù)庫(kù)進(jìn)行預(yù)填充:

  • 選擇生產(chǎn)環(huán)境數(shù)據(jù)的子集來(lái)運(yùn)行黑盒測(cè)試;
  • 運(yùn)行黑盒測(cè)試之前把手工構(gòu)造的數(shù)據(jù)填充到數(shù)據(jù)庫(kù)中。

此外,有了黑盒測(cè)試并不意味著不需要單元測(cè)試,針對(duì) API 的單元測(cè)試還是需要編寫(xiě)的。

6. 使用基于 JWT 的無(wú)狀態(tài)的認(rèn)證機(jī)制

因?yàn)?Rest API 必須是無(wú)狀態(tài)的,因此認(rèn)證機(jī)制也需要是無(wú)狀態(tài)的,而基于 JWT(JSON Web Token) 的認(rèn)證機(jī)制是無(wú)狀態(tài)認(rèn)證機(jī)制中的最佳解決方案。

JWT 的認(rèn)證機(jī)制包含三部分:

  1. Header:包含 token 的類(lèi)型和哈希算法;
  2. payload:包含聲明信息;
  3. signature:JWT 實(shí)際上并不是對(duì) payload 進(jìn)行加密,只是對(duì)其做了簽名;

為 API 添加基于 JWT 的認(rèn)證機(jī)制也非常的簡(jiǎn)單,比如下面的代碼:

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ù)。如果要訪問(wèn)這種被保護(hù)的接口,需要使用 Authorization Header 來(lái)提供 token,比如:

curl --Header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" my-website.com

你可能注意到了,JWT 模塊并不依賴(lài)任何數(shù)據(jù)存儲(chǔ)層,這是因?yàn)?token 本身是可以單獨(dú)被校驗(yàn)的,token 里面的 payload 甚至可以包含 token 的簽名時(shí)間、有效期限。

此外,你還需要確保,所有的 API 接口只能通過(guò)更安全的 HTTPS 鏈接來(lái)訪問(wèn)。

7. 學(xué)會(huì)使用條件請(qǐng)求機(jī)制

條件請(qǐng)求機(jī)制是基于不同的 Header 表現(xiàn)出不同的行為的機(jī)制,可以認(rèn)為這些 Header 就是請(qǐng)求處理方式的先決條件,如果條件滿足,請(qǐng)求處理方式就會(huì)有所不同。

可以利用這些 Header 檢測(cè)服務(wù)器上的資源版本是否匹配特定的資源版本,這些 Header 的取值可以是如下的內(nèi)容:

  • 資源的最后修改時(shí)間;
  • 資源的標(biāo)簽(隨資源變化而變化);

具體來(lái)說(shuō):

  • Last-Modified:標(biāo)識(shí)資源的最新修改時(shí)間;
  • Etag:標(biāo)識(shí)資源的標(biāo)簽;
  • If-Modified-Since:結(jié)合 Last-Modified Header 使用;
  • If-Non-Match:結(jié)合 Etag 使用;

下面來(lái)看一個(gè)實(shí)際的例子:

客戶端不知道 doc 資源的任何版本,所以請(qǐng)求時(shí)即不能提供 If-Modified-Since,也不能提供 If-Non-Match 兩個(gè) Header,然后服務(wù)端在響應(yīng)中會(huì)增加 Etag 和 Last-Modified 兩個(gè) Header。

接下來(lái),客戶端再次請(qǐng)求相同的資源的時(shí)候,就可以帶上 If-Modified-Since 和 If-Non-Match 這兩個(gè) Header 了,然后如果服務(wù)器端會(huì)檢查資源是否修改,如果沒(méi)有修改,直接返回 304 – Not Modified 狀態(tài)碼,而不重復(fù)發(fā)送資源的內(nèi)容。

8. 擁抱接口調(diào)用頻率限制(Rate-Limiting)

頻率限制是用來(lái)控制調(diào)用方有對(duì)接口發(fā)起請(qǐng)求的次數(shù),為了讓你的 API 用戶知道他們還剩下多少余額,可以設(shè)置下面的 Header:

  • X-Rate-Limit-Limit:特定時(shí)間段內(nèi)允許的最多請(qǐng)求次數(shù);
  • X-Rate-Limit-Remaining:特定時(shí)間段內(nèi)剩余的請(qǐng)求次數(shù);
  • X-Rate-Limit-Reset:什么時(shí)候請(qǐng)求頻率限制次數(shù)會(huì)重置;

大多數(shù)的 WEB 框架都支持上面這些 Header,如果內(nèi)置不支持,也可以找到插件來(lái)支持,比如,如果你使用了 koa,可以使用 koa-rate-limit

需要注意的是,不同的 API 服務(wù)提供商頻率限制的時(shí)間窗差異會(huì)很大,比如 GitHub 是 60 分鐘,而 Twitter 是 15 分鐘。

9. 編寫(xiě)良好的 API 文檔

編寫(xiě) API 的目的當(dāng)然是讓別人使用并受益,提供良好的接口文檔至關(guān)重要。下面這兩個(gè)開(kāi)源項(xiàng)目可以幫你創(chuàng)建 API 文檔:

如果你愿意使用第三方文檔服務(wù)商,可以考慮 Apiary。

10. 對(duì) API 技術(shù)演化保持關(guān)注

過(guò)去幾年中,API 技術(shù)方案領(lǐng)域出現(xiàn)了兩種新的查詢(xún)語(yǔ)言,分別是 Facebook 的 GraphQL 和 Netflix 的 Falcor,為什么需要他們呢?

試想這種 API 接口請(qǐng)求:/org/1/space/2/docs/1/collaborators?include=email&page=1&limit=10,類(lèi)似的情況會(huì)讓 API 很快失控,如果你希望所有接口能返回類(lèi)似的響應(yīng)格式,那么 GraphQL 和 Falcor 就能幫你解決這個(gè)問(wèn)題。

關(guān)于 GraphQL

GraphQL 是一種用于 API 的查詢(xún)語(yǔ)言,也是一種基于現(xiàn)有數(shù)據(jù)處理數(shù)據(jù)查詢(xún)的運(yùn)行時(shí)。GraphQL 為您的 API 中的數(shù)據(jù)提供了一個(gè)完整和可理解的描述,使用戶能夠準(zhǔn)確地詢(xún)問(wèn)他們需要什么,使得隨著時(shí)間推移的 API 演化更容易,GraphQL 還有強(qiáng)大的開(kāi)發(fā)工具支持。 到這里閱讀更多。

關(guān)于 Falcor

Falcor 是支撐著 Netflix UI 的創(chuàng)新數(shù)據(jù)平臺(tái)。Falcor 允許你將所有后端數(shù)據(jù)建模為 Node.js 服務(wù)商的單個(gè)虛擬 JSON 對(duì)象。在客戶端可以使用熟悉的 JavaScript 操作、處理遠(yuǎn)程JSON對(duì)象。如果你知道你的數(shù)據(jù),你就知道你的 API 長(zhǎng)啥樣。 到這里閱讀更多。

能帶來(lái)靈感的優(yōu)秀 API 設(shè)計(jì)

如果你正在開(kāi)發(fā) Rest API 或者準(zhǔn)備改進(jìn)老版本的 API,這里收集了幾個(gè)在線上提供服務(wù)、設(shè)計(jì)優(yōu)秀并且非常直接借鑒的 API:

希望讀到這里的同學(xué)對(duì)如何用 Node.js 編寫(xiě)良好的 API 有更好的理解,如果有建議,歡迎評(píng)論中提出。

責(zé)任編輯:張燕妮 來(lái)源: 王仕軍
相關(guān)推薦

2023-12-06 07:13:16

RESTAPI客戶端

2023-04-28 08:42:22

Node.js開(kāi)源項(xiàng)目

2023-09-12 06:55:27

2021-08-20 09:00:00

Node.js開(kāi)發(fā)API

2023-04-18 15:18:10

2025-03-18 00:10:00

2015-06-24 10:07:34

Java編碼最佳實(shí)踐

2023-03-02 19:53:13

DirectusCMS管理

2022-01-07 08:00:00

Node.js開(kāi)發(fā)Web

2024-05-13 13:13:13

APISpring程序

2012-10-29 09:30:47

HadoopHadoop集群Hadoop生態(tài)系統(tǒng)包

2024-09-23 00:00:00

下拉菜單UI控件

2012-09-03 10:33:43

2023-08-03 16:14:06

JavaScriptAPI

2023-05-24 12:33:35

2024-11-29 10:00:00

Python日志記錄

2023-11-19 20:16:43

RESTAPIPOST

2016-08-11 14:02:02

NodeJS前端

2022-09-04 15:54:10

Node.jsAPI技巧

2023-01-10 14:11:26

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)