使用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。

相关文章
相关标签/搜索