当前位置: 首页 > 后端技术 > Node.js

Node.jsRestAPI编写的10个最佳实践

时间:2023-04-03 17:46:47 Node.js

Node.js除了可以编写WEB应用之外,还可以用来编写API服务。实践,包括如何命名路由、进行认证和测试等。内容总结如下:正确使用HTTP方法和路由正确使用HTTP状态码使用HTTPHeader发送元数据为RESTAPI选择合适的框架黑盒API测试使用基于JWT的无状态认证机制学习使用条件请求机制拥抱接口调用频率限制(Rate-Limiting)写好API文档关注API技术演进 1.正确使用HTTP方法和路由  想象一下,你正在构建一个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,设置status代码很简单:res.status(500).send({error:'Internalservererrorhappen'}),如果使用restify,类似:res.status(201)。  如果您想查看HTTP状态代码的完整列表,请单击此处。 3。使用HTTPHeader发送元数据  如果要发送有关响应主体数据的元数据,可以使用Header。Header可以包含的公共元数据包括以下几类:分页信息;频率限制信息;认证信息;  如果需要在HeaderMetadata中发送自定义,最好的方法是在Header名称前加上X,比如需要发送CSRFToken时,实际的Header应该命名为:X-CSRF-Token但是,这个Header在RFC6648上已经被废弃了。API在设置自定义标头时应尽可能避免命名冲突。例如,为了实现这个目标,OpenStack在所有的API自定义头中添加了一个OpenStack前缀:OpenStack-Identity-Account-IDOpenStack-Networking-Host-NameOpenStack-Object-Storage-Policy  需要注意的是虽然HTTP规范没有规定Header的大小,但是Node.js中Header的大小限制在80KB。官方正文如下:不要让HTTPHeader的整体大小,包括状态码行,超过HTTP_MAX_Header_SIZE。这样做的目的是防御基于标头的DDOS攻击。点击此处 4。为RESTAPI选择合适的框架  根据自己的实际场景选择合适的框架非常重要。Node.js中的框架大致介绍如下:  Express、Koa、HAPI  Express、Koa、HAPI主要用于构建浏览器WEB应用,因为它们都支持服务端模板渲染,虽然这只是它们众多功能中的一个。如果你的应用需要提供用户界面,那么这三个都是不错的选择。  Restify  Restify专门用于创建符合REST规范的服务。它诞生的目的是帮助您构建严格可维护的API服务。Restify内置了对所有请求处理函数的DTrace支持。并且已经被npm和netflix用来在生产环境中提供重要的服务。 5.对API进行黑盒测试  测试API的最佳方法是对它们执行黑盒测试。黑盒测试是一种不关心应用程序内部结构和工作原理的测试方法。在测试期间不应模拟系统的任何部分。  supertest是可用于接口黑盒测试的模块之一。下面是基于测试框架mocha编写的测试用例。这个用例的目的是检查接口是否可以返回单条用户数据:constrequest=require('supertest')describe('GET/user/:id',function(){it('returnsauser',function(){//较新的mocha版本也接受promisesreturnrequest(app).get('/user').set('Accept','application/json').expect(200,{id:'1',name:'JohnMath'},done);});});  也许有人会问:连接到API服务的数据库中的数据是怎么写的?  一般来说,在写测试的时候,尽量不要对系统的状态做假设。但是,在某些场景中,您需要确切地知道系统的当前状态才能添加更多断言以提高测试覆盖率。速度。如果您有这样的需求,可以尝试以下方法预填充数据库:选择生产环境数据的一个子集运行黑盒测试;在运行黑盒测试之前将手动构造的数据填充到数据库中。  另外,有黑盒测试不代表不需要单元测试,API的单元测试还是要写的。 6.使用基于JWT的无状态认证机制  因为RestAPI必须是无状态的,所以认证机制也需要是无状态的,而基于JWT(JSONWebToken)的认证机制是无状态认证机制中最好的解决方案。  JWT的认证机制由三部分组成:Header:包含token类型和hash算法;payload:包含语句信息;signature:JWT实际上并不对payload进行加密,只是对其进行签名;  在API中添加基于JWT的认证机制也很简单,比如如下代码:constkoa=require('koa');constjwt=require('koa-jwt');constapp=koa();app.use(jwt(secret:'very-secret'}));//受保护的中间件app.use(function*()//令牌的内容将在this.state.user上可用this.body={secret:'42'}});  有了上面的代码,你的API就被JWT保护了。如果要访问这种被保护的接口,需要使用AuthorizationHeader来提供token,比如:curl--Header"Authorization:BearereyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"my-website.com  你可能注意到了,JWT模块并Itdoesnotrelyonanydatastoragelayer,becausethetokenitselfcanbeverifiedindependently,andthepayloadinthetokencan甚至包括令牌的签名时间和到期日期。  此外,您还需要确保所有API接口只能通过更安全的HTTPS链接访问。 7.学会使用条件请求机制  条件请求机制是基于不同的header表现出不同的行为的机制。可以认为这些头部是请求处理方法的前提条件。如果满足条件,则更改请求处理方法。不同的。  可以使用这些headers来检测服务器上的资源版本是否匹配特定的资源版本。这些标头的值可以是:资源的最后修改时间;资源的标签(随资源变化);  具体来说:Last-Modified:标识资源的最新修改时间;etag:标识资源的标签;If-Modified-Since:与Last-ModifiedHeader结合使用;If-Non-Match:与Etag结合使用;  看一个实际的例子:  客户端不知道doc资源的任何版本,所以在请求时不能提供If-Modified-Since或If-Non-Match两个header,然后服务端响应添加了两个标头,Etag和Last-Modified。  nodejs-resftul-api-with-conditional-request-without-previous-versions.png  接下来客户端再次请求同一个资源时,可以带上If-Modified-Since和If-Non-Match这两个Header,然后如果服务器会检查资源是否被修改,如果没有,直接返回304-NotModified状态码,不再重复发送资源的内容。  nodejs-resftul-api-with-conditional-request-with-previous-versions.png 8.拥抱接口调用频率限制(Rate-Limiting)  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文档:APIBlueprintSwagger  如果你愿意使用第三方文档服务商,可以考虑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用户界面提供支持的创新数据平台。Falcor允许您将所有后端数据建模为Node.js服务器的单个虚拟JSON对象。在客户端,您可以使用熟悉的JavaScript操作来处理远程JSON对象。如果你了解你的数据,你就会知道你的API是什么样子的。去这里阅读更多。 优秀的API设计,能带来灵感  如果你正在开发RestAPI,或者准备改进旧版本的API,这里有几个API提供在线服务,设计优秀,非常直接参考:GitHubAPITwilioAPIStripeAPIDigitalOceanAPI  我希望阅读本文的同学对如何使用Node.js编写好的API有更好的理解。如果您有任何建议,请在评论中提出。英文原文:https://blog.risingstack.com/10-best-practices-for-writing-node-js-rest-apis/