本文首发于之乎专栏前端周刊,全文共 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
的最好实践,包括怎样定名路由、举行认证和测试等话题,内容摘要以下:
正确运用
HTTP Method
和路由正确的运用
HTTP
状况码运用
HTTP Header
来发送元数据为
REST API
遴选适宜的框架要对
API
举行黑盒测试运用基于
JWT
的无状况的认证机制学会运用前提要求机制
拥抱接口挪用频次限定(Rate-Limiting)
编写优越的
API
文档对
API
手艺演变坚持关注
1. 正确运用 HTTP Method 和路由
试想你正要构建一个 API
用来建立、更新、猎取、删除用户,关于这些操纵,HTTP
范例内里已有了现成的操纵:POST
、PUT
、GET
、DELETE
,提议直接运用他们来形貌接口的行动。
至于路由的定名,应当运用名词或名词性短语来作为资本标识符,比方上文提到的用户治理的例子,路由就应当长如许:
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
来发送元数据
假如想要发送关于相应体数据的元数据,可以运用 Header
,Header
可以包括的罕见元数据包括以下几类:
分页信息;
频次限定信息;
认证信息;
假如你须要在 Header
中发送自定义的元数据,最好的做法是在 Header
称号前面加 X
,比方,须要发送 CSRF Token
的时刻,现实的 Header
应当定名为:X-CSRF-Token
,然则,这类 Header
在 RFC 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,如许做的目标是为了防备基于Header
的DDOS
进击。点击这里
4. 为 REST API 遴选适宜的框架
依据你的现实场景遴选适宜的框架是异常主要的,Node.js
中的框架大抵引见以下:
Express、Koa、HAPI
Express、Koa、HAPI 主如果用来构建浏览器 WEB
运用,由于他们都支撑效劳端模板衬着,虽然这只是他们浩瀚功用中的一个。假如你的运用须要供应用户界面,那末这三个就是不错的挑选。
Restify
而 Restify 是特地用来建立相符 REST
范例的效劳的,他降生的目标就是帮你构建严厉意义上的、可庇护的 API
效劳。Restify
内置了一切要求处置惩罚函数的 DTrace 支撑。而且已被 npm 和 netflix 用来在临盆环境供应主要的效劳。
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
的认证机制包括三部份:
Header
:包括token
的范例和哈希算法;payload
:包括声明信息;signature
:JWT
现实上并非对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,然后效劳端在相应中会增添 Etag
和 Last-Modified
两个 Header
。
接下来,客户端再次要求雷同的资本的时刻,就可以够带上 If-Modified-Since
和 If-Non-Match
这两个 Header
了,然后假如效劳器端会搜检资本是不是修正,假如没有修正,直接返回 304 - Not Modified
状况码,而不重复发送资本的内容。
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
手艺计划范畴涌现了两种新的查询言语,分别是 Facebook
的 GraphQL
和 Netflix
的 Falcor
,为何须要他们呢?
试想这类 API 接口要求:/org/1/space/2/docs/1/collaborators?include=email&page=1&limit=10
,相似的状况会让 API 很快失控,假如你愿望一切接口能返回相似的相应花样,那末 GraphQL
和 Falcor
就可以帮你处理这个题目。
关于 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
想直接在微信中定阅前端周刊?扫下方二维码关注前端周刊定阅号。
想和我面对面交换?扫下方二维码增加我为挚友。
Happy Hacking