使用Node.js開發REST APIs的10個最佳實踐(翻譯)

原文:blog.risingstack.com/10-best-pra… 這篇文章涵蓋了使用Node.js開發REST APIs的最佳實踐,包括如何定義路由、用戶鑑權、黑盒測試和正確使用緩存頭等。javascript

雖然開發REST APIs是Node.js的主要用途之一,可是在咱們使用Trace幫助客戶尋找應用中的問題時,咱們發現不少開發者在開發REST API時依然存在許多問題。java

因此咱們但願如下的實踐能夠幫助到你們:node

1. 使用HTTP方法和API路由

想象一下,當你正在使用Node.js開發users的CRUD接口,對於這樣的業務HTTP早就有了充足的工具集:POST、GET、PUT、PATCH和DELETE。web

做爲一個最佳實踐,你的API路由應該始終使用名詞來命名。針對剛纔的users來講,api命名應該相似下面這樣:算法

  • 建立用戶:POST /user 或者 put /user/:id
  • 獲取用戶:GET /user GET /user/:id
  • 更新用戶:PATCH /user/:id
  • 刪除用戶:DELETE /user/:id

API應該始終使用名詞來命名!數據庫

2. 正確使用HTTP狀態碼

若是請求一個接口時產生了錯誤,你應該在響應中使用正確的狀態碼:json

  • 2xx:一切正常
  • 3xx:資源重定向
  • 4xx:由於客戶端的錯誤致使請求沒法被響應
  • 5xx:服務端錯誤

若是你用的是Express,設置狀態碼會很是簡單:後端

res.status(500).send({error: 'Internal server error happened'}).
複製代碼

3. 使用HTTP headers發送元數據

與請求體相關的元數據可使用HTTP headers發送,例如:api

  • 分頁信息
  • 限流
  • 用戶鑑權

若是你須要在標題中設置任何自定義元數據,最好在它們前面加上X。例如,若是你使用的是CSRF token,那麼將它們命名爲X-Csrf-Token是一種常見的(但非標準的)方式。可是這種方式也已經被廢棄。新API應盡最大努力不使用可能與其餘應用程序衝突的標頭名稱。例如,OpenStack使用OpenStack爲其標頭添加前綴:promise

OpenStack-Identity-Account-ID
OpenStack-Networking-Host-Name
OpenStack-Object-Storage-Policy
複製代碼

請注意,HTTP標準沒有定義headers的任何大小限制;可是在實際使用中發現,Node.js(撰寫本文時)對header對象強加了80KB的大小限制。

4. 使用合適的框架來開發REST APIs

選擇最適合你的項目的框架很是重要。

Express, Koa or Hapi

ExpressKoaHapi可用於建立瀏覽器應用程序,所以,它們支持模板和渲染-僅舉幾個功能。若是您的應用程序也須要提供面向用戶的一面,那麼爲它們提供幫助是有意義的。

Restify

另外一方面,Restify專一於幫助您構建REST服務。它的存在是爲了讓您構建可維護和可觀察的「嚴格」API服務。Restify還爲全部處理程序提供自動DTrace支持。

5. 對你的REST APIs進行黑盒測試

測試REST API的最佳方法之一是將它們視爲黑盒子。

黑盒測試是一種測試應用程序功能的方法,在不瞭解其內部結構或工做原理的狀況下進行檢查。所以,沒有任何依賴項被模擬或存根,但系統做爲一個總體進行測試。

其中一個能夠幫助您進行黑盒測試Node.js REST API的模塊是supertest

使用測試運行器mocha檢查用戶是否返回的簡單測試用例能夠像這樣實現:

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)
  })
})
複製代碼

您可能會問:數據如何填充到爲REST API提供服務的數據庫中?

通常來講,以一種儘量少的關於系統狀態的假設的方式編寫測試是一種很好的方法。儘管如此,在某些狀況下,當您須要準確瞭解系統的狀態時,您能夠找到本身的位置,這樣您就能夠進行斷言並得到更高的測試覆蓋率。

所以,根據您的需求,您可使用如下方法之一使用測試數據填充數據庫:

  • 在已知的生產數據子集上運行黑盒測試場景
  • 在運行測試用例以前,使用精心設計的數據填充數據庫

固然,黑盒測試並不意味着你沒必要進行單元測試,你仍然須要爲你的API編寫單元測試。

6. 作基於JWT的無狀態認證

因爲您的REST API必須是無狀態的,所以您的身份驗證層也是如此。爲此,JWT(JSON Web Token)是理想的選擇。

JWT由三部分組成:

  • Header:包含令牌的類型和散列算法
  • Payload:包含聲明
  • Signature:JWT不加密有效載荷,必須簽名!

將基於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標頭字段中提供令牌。

curl --header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" my-website.com 
複製代碼

您能夠注意到的一件事是JWT模塊不依賴於任何數據庫層。狀況就是這樣,由於全部JWT令牌均可以本身驗證,而且它們也能夠包含生存時間值。

此外,您始終必須確保只能經過使用HTTPS的安全鏈接訪問全部API端點。

7. 使用條件請求

條件請求是HTTP請求,根據特定的HTTP標頭執行不一樣的HTTP請求。您能夠將這些標頭視爲先決條件:若是知足這些標頭,則將以不一樣的方式執行請求。這些標頭嘗試檢查服務器上存儲的資源版本是否與同一資源的給定版本匹配。因爲這個緣由,這些標題能夠是:

  • 最後一次修改的時間戳
  • 或實體標籤,每一個版本都有所不一樣

這些標籤包括:

  • Last-Modified (標明資源上次修改的時間)
  • Etag (標明實體標籤)
  • If-Modified-Since (使用Last-Modified)
  • If-None-Match (使用Etag)

8. 擁抱限流

用於控制給定消費者能夠向API發送的請求數量。

要告訴您的API用戶他們剩下多少請求,請設置如下標頭:

  • X-Rate-Limit-Limit, 給定時間間隔內容許的請求數
  • X-Rate-Limit-Remaining, 相同時間段內剩下的請求數
  • X-Rate-Limit-Reset, 請求數重置時間

大多數HTTP框架都支持開箱即用(或使用插件)。例如,若是您使用Koa,則有koa-ratelimit包。

9. 建立優雅的接口文檔

您編寫API以便其餘人可使用它們從中受益。爲Node.js REST API提供API文檔相當重要。如下開源項目能夠幫助您爲API建立文檔:

  • API Blueprint
  • Swagger 或者,若是您想使用託管產品,您能夠選擇Apiary。

10. 不要忘記接口的未來使用者

在過去幾年中,出現了兩種主要的API查詢語言 - 即來自Facebook的GraphQL和來自Netflix的Falcor。但爲何咱們甚至須要它們呢? 想象一下如下RESTful資源請求:

/org/1/space/2/docs/1/collaborators?include=email&page=1&limit=10
複製代碼

這可能很容易失控 - 由於您但願始終爲全部模型得到相同的響應格式。這是GraphQL和Falcor能夠提供幫助的地方。

GraphQL是API的查詢語言,是使用現有數據完成這些查詢的運行時。GraphQL提供了API中數據的完整且易於理解的描述,使客戶可以準確地詢問他們須要什麼,僅此而已,使API隨着時間的推移更容易發展,並啓用強大的開發人員工具。

Falcor是爲Netflix UI提供支持的創新數據平臺。 Falcor容許您將全部後端數據建模爲節點服務器上的單個Virtual JSON對象。在客戶端上,您可使用熟悉的JavaScript操做(如get,set和call)來處理遠程JSON對象。若是您瞭解本身的數據,就會知道本身的API。

我但願你如今能更好地理解如何使用Node.js編寫API。

相關文章
相關標籤/搜索