编写 Node.js Rest API 的 10 个最好实践

本文首发于之乎专栏前端周刊,全文共 6953 字,读完需 8 分钟,速率需 2 分钟。翻译自:RingStack 的文章 https://blog.risingstack.com/10-best-practices-for-writing-node-js-rest-apis/,英文好的同砚可以直接浏览原文,译文较原文有删省。

Node.js 除了用来编写 WEB 运用以外,还可以用来编写 API 效劳,我们在本文中会引见编写 Node.js Rest API 的最好实践,包括怎样定名路由、举行认证和测试等话题,内容摘要以下:

  1. 正确运用 HTTP Method 和路由

  2. 正确的运用 HTTP 状况码

  3. 运用 HTTP Header 来发送元数据

  4. REST API 遴选适宜的框架

  5. 要对 API 举行黑盒测试

  6. 运用基于 JWT 的无状况的认证机制

  7. 学会运用前提要求机制

  8. 拥抱接口挪用频次限定(Rate-Limiting)

  9. 编写优越的 API 文档

  10. API 手艺演变坚持关注

1. 正确运用 HTTP Method 和路由

试想你正要构建一个 API 用来建立、更新、猎取、删除用户,关于这些操纵,HTTP 范例内里已有了现成的操纵:POSTPUTGETDELETE,提议直接运用他们来形貌接口的行动。

至于路由的定名,应当运用名词或名词性短语来作为资本标识符,比方上文提到的用户治理的例子,路由就应当长如许:

  • POST /users 或许 PUT /users/:id 用来建立新用户;

  • GET /users 用来猎取用户列表;

  • GET /users/:id 用来猎取单个用户;

  • PATCH /users/:id 用来更新用户信息;

  • DELETE /users/:id 用来删除用户;

2. 正确的运用 HTTP 状况码

假如效劳器端在要求处置惩罚的历程中出错了,你必需设置正确的相应状况码,详细以下:

  • 2xx,示意一切正常;

  • 3xx,示意资本位置已变动;

  • 4xx,示意由于客户端毛病而致使要求没法被处置惩罚,比方参数校验没经由过程;

  • 5xx,示意由于效劳器毛病致使要求没法被处置惩罚,比方效劳端抛了异常;

假如你运用 express,设置状况码异常简朴:res.status(500).send({ error: 'Internal server error happend' }),假如运用了 restify,也是相似的:res.status(201)

假如想看完全的 HTTP 状况码,点击这里

3. 运用 HTTP Header 来发送元数据

假如想要发送关于相应体数据的元数据,可以运用 HeaderHeader 可以包括的罕见元数据包括以下几类:

  • 分页信息;

  • 频次限定信息;

  • 认证信息;

假如你须要在 Header 中发送自定义的元数据,最好的做法是在 Header 称号前面加 X,比方,须要发送 CSRF Token 的时刻,现实的 Header 应当定名为:X-CSRF-Token,然则,这类 HeaderRFC 6648 中已被烧毁了。API 在设置自定义 Header 的时刻还要尽量防止定名争执,比方为了到达这个目标OpenStack 为一切 API 的自定义 Header 都加上了 OpenStack 的前缀:

OpenStack-Identity-Account-ID  
OpenStack-Networking-Host-Name  
OpenStack-Object-Storage-Policy  

须要注重的是,虽然 HTTP 范例中没有划定 Header 的大小,然则 Node.js 中 Header 的大小被限定在了 80KB。官方原文以下:

不要让 HTTP Header ,包括个中状况码那行的团体大小凌驾 HTTP_MAX_Header_SIZE,如许做的目标是为了防备基于 HeaderDDOS 进击。点击这里

4. 为 REST API 遴选适宜的框架

依据你的现实场景遴选适宜的框架是异常主要的,Node.js 中的框架大抵引见以下:

Express、Koa、HAPI

ExpressKoaHAPI 主如果用来构建浏览器 WEB 运用,由于他们都支撑效劳端模板衬着,虽然这只是他们浩瀚功用中的一个。假如你的运用须要供应用户界面,那末这三个就是不错的挑选。

Restify

Restify 是特地用来建立相符 REST 范例的效劳的,他降生的目标就是帮你构建严厉意义上的、可庇护的 API 效劳。Restify 内置了一切要求处置惩罚函数的 DTrace 支撑。而且已被 npmnetflix 用来在临盆环境供应主要的效劳。

5. 要对 API 举行黑盒测试

测试 API 的最好要领是对他们举行黑盒测试,黑盒测试是一种不关心运用内部结构和事情道理的测试要领,测试时体系任何部份都不应当被 mock

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);
  });
});

可以有人会问:API 效劳所衔接的数据库内里的数据是怎样写进去的呢?

一般来讲,你写测试的时刻,要尽量不对体系状况做假定,然则在某些场景下,你须要正确的晓得体系当前所处的状况以增添更多的断言来进步测试覆蓋率。假如你有这类需求,你可以试用以下的要领对数据库举行预添补:

  • 挑选临盆环境数据的子集来运转黑盒测试;

  • 运转黑盒测试之前把手工组织的数据添补到数据库中。

另外,有了黑盒测试并不意味着不须要单元测试,针对 API单元测试照样须要编写的。

6. 运用基于 JWT 的无状况的认证机制

由于 Rest API 必需是无状况的,因而认证机制也须如果无状况的,而基于 JWT(JSON Web Token) 的认证机制是无状况认证机制中的最好处理计划。

JWT 的认证机制包括三部份:

  1. Header:包括 token 的范例和哈希算法;

  2. payload:包括声明信息;

  3. signatureJWT 现实上并非对 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 模块并不依靠任何数据存储层,这是由于 token 自身是可以零丁被校验的,token 内里的 payload 以至可以包括 token 的署名时候、有效期限。

另外,你还须要确保,一切的 API 接口只能经由过程更平安的 HTTPS 链接来接见。

7. 学会运用前提要求机制

前提要求机制是基于差别的 Header 表现出差别的行动的机制,可以以为这些 Header 就是要求处置惩罚方式的先决前提,假如前提满足,要求处置惩罚方式就会有所差别。

可以应用这些 Header 检测效劳器上的资本版本是不是婚配特定的资本版本,这些 Header 的取值可以是以下的内容:

  • 资本的末了修正时候;

  • 资本的标签(随资本变化而变化);

详细来讲:

  • Last-Modified:标识资本的最新修正时候;

  • Etag:标识资本的标签;

  • If-Modified-Since:连系 Last-Modified Header 运用;

  • If-Non-Match:连系 Etag 运用;

下面来看一个现实的例子:

客户端不晓得 doc 资本的任何版本,所以要求时即不能供应 If-Modified-Since,也不能供应 If-Non-Match 两个 Header,然后效劳端在相应中会增添 EtagLast-Modified 两个 Header

《编写 Node.js Rest API 的 10 个最好实践》

接下来,客户端再次要求雷同的资本的时刻,就可以够带上 If-Modified-SinceIf-Non-Match 这两个 Header 了,然后假如效劳器端会搜检资本是不是修正,假如没有修正,直接返回 304 - Not Modified 状况码,而不重复发送资本的内容。

《编写 Node.js Rest API 的 10 个最好实践》

8. 拥抱接口挪用频次限定(Rate-Limiting)

频次限定是用来掌握挪用方有对接口提议要求的次数,为了让你的 API 用户晓得他们还剩下若干余额,可以设置下面的 Header

  • X-Rate-Limit-Limit:特定时候段内许可的最多要求次数;

  • X-Rate-Limit-Remaining:特定时候段内盈余的要求次数;

  • X-Rate-Limit-Reset:什么时刻要求频次限定次数会重置;

大多数的 WEB 框架都支撑上面这些 Header,假如内置不支撑,也可以找到插件来支撑,比方,假如你运用了 koa,可以运用 koa-rate-limit

须要注重的是,差别的 API 效劳供应商频次限定的时候窗差别会很大,比方 GitHub 是 60 分钟,而 Twitter 是 15 分钟。

9. 编写优越的 API 文档

编写 API 的目标当然是让他人运用并受益,供应优越的接口文档至关主要。下面这两个开源项目可以帮你建立 API 文档:

假如你情愿运用第三方文档效劳商,可以斟酌 Apiary

10. 对 API 手艺演变坚持关注

过去几年中,API 手艺计划范畴涌现了两种新的查询言语,分别是 FacebookGraphQLNetflixFalcor,为何须要他们呢?

试想这类 API 接口要求:/org/1/space/2/docs/1/collaborators?include=email&page=1&limit=10,相似的状况会让 API 很快失控,假如你愿望一切接口能返回相似的相应花样,那末 GraphQLFalcor 就可以帮你处理这个题目。

关于 GraphQL

GraphQL 是一种用于 API 的查询言语,也是一种基于现有数据处置惩罚数据查询的运转时。GraphQL 为您的 API 中的数据供应了一个完全和可明白的形貌,运用户可以正确地讯问他们须要什么,使得跟着时候推移的 API 演变更轻易,GraphQL 另有壮大的开辟工具支撑。 到这里浏览更多。

关于 Falcor

Falcor 是支撑着 Netflix UI 的立异数据平台。Falcor 许可你将一切后端数据建模为 Node.js 效劳商的单个假造 JSON 对象。在客户端可以运用熟习的 JavaScript 操纵、处置惩罚长途JSON对象。假如你晓得你的数据,你就晓得你的 API 长啥样。 到这里浏览更多。

能带来灵感的优异 API 设想

假如你正在开辟 Rest API 或许预备革新老版本的 API,这里收集了几个在线上供应效劳、设想优异而且异常直接自创的 API

愿望读到这里的同砚对怎样用 Node.js 编写优越的 API 有更好的明白,假如有提议,迎接批评中提出。

One More Thing

想直接在微信中定阅前端周刊?扫下方二维码关注前端周刊定阅号。
《编写 Node.js Rest API 的 10 个最好实践》

想和我面对面交换?扫下方二维码增加我为挚友。

《编写 Node.js Rest API 的 10 个最好实践》

Happy Hacking

    原文作者:wangshijun
    原文地址: https://segmentfault.com/a/1190000008537712
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞