接口文件 - 985ch/egg-sachikawa GitHub Wiki
接口文件是指那些放在app/http目录下,用于实现具体接口的脚本文件。
接口文件的定位主要是作为接口的配置存在的,因此不宜在接口文件中编写复杂的业务逻辑。建议把复杂的业务逻辑都写入Controller和Service中供接口文件使用。
每个接口文件都需要导出一个以Application对象为参数的函数,并且该函数返回一个接口配置JSON。
一个典型的接口文件如下:
// app/http/get/greet.js
'use strict';
module.exports = app => {
return {
params: { name: 'string' },
async controller() {
const { name } = this.state.params;
this.success(`hello ${name}`);
},
};
};以上脚本将会生成一个路由为[GET]/greet的接口,该接口接受一个字符串类型的参数name,在调用时会根据传入的name返回一个有着特定结构的JSON数据。如:调用/greet?name=123,得到结果{"code":0,"data":"hello 123"}。
根据接口文件返回的JSON的不同,接口参数和返回结果也会各不相同。
| 字段 | 对应中间件 | 字段介绍 |
|---|---|---|
| name | 无 | 接口的路由名字,一般不使用 |
| path | 无 | 接口的路由路径,一般不使用 |
| controller | 无 | 接口控制器,必备字段,具体介绍详见控制器 |
| params | params | 接口参数配置,具体介绍详见参数配置 |
| ip | ipfilter | IP限制配置,具体介绍详见IP限制 |
| cache | cache | 结果缓存配置,具体介绍详见结果缓存 |
| compress | compress | 结果压缩配置,具体介绍详见结果压缩 |
controller对应egg.js的控制器,controller可以是以下三种对象的其中一种:
-
一个没有参数的异步函数。 如
async controller() {}。若controller的内容非常简单,则推荐使用这种写法。但是需要注意的是,采用这种写法的时候,为了避免无法正常获取this指针,不能将函数写成controller: async () =>{}的形式 -
一个控制器对象。 如
app.controller.action.pay。这种方法是egg推荐的形式,但是需要专门编写controller文件。 -
一个对应控制器对象的字符串。 如
'action.pay'。这种方法是上一种方法的简化形式。
在controller内可以通过this指针获得请求上下文对象Context,这个对象封装了这次用户请求的信息,并提供了许多便捷的方法来获取请求参数或者设置响应信息。而sachikawa的上下文对象除了继承egg.js的上下文对象以外,还额外追加了不少内容,以让开发变得更为便捷。
关于上下文对象的具体信息请查阅egg.js的相关文档。
为了更加方便的返回结果,sachikawa框架给上下文对象追加了三个方法。他们分别是:
- Context.success(data, msg) 这个方法应在接口调用成功时调用,这个接口的两个参数按顺序分别是结果数据和结果消息。这两个参数可以从右至左省略。注意:若调用该方法时已经在其他任何地方填写过返回结果,则会在后台输出一条错误信息
- Context.fail(msg, code, data) 这个方法应在接口调用有问题时使用,这个接口的三个参数按顺序分别是错误消息,错误编码和错误数据,这三个参数均可以从右至左省略。
- Context.throwFail(msg, code, data) 这个方法基本等同于Context.fail方法,区别在于Context.fail方法通常写在控制器中,而该方法则是通过抛出特定错误的方式来实现 从任意位置直接返回错误到前端,并停止执行接下来的代码。 不建议使用该方法来代替普通的错误返回,因为该方法可能让开发者在调试的时候难以找到程序的中断点。但是在确实需要抛出某种错误的时候,使用该方法会有很好的效果。
框架的默认返回结果是一个JSON,该JSON各字段如下
| 字段 | 类型 | 说明 |
|---|---|---|
| code | Integer | 错误编码。调用success方法时,code=0;调用fail方法并且没有设定code时,code=-1 |
| msg | String | 错误或成功消息,该字段可以为undefined |
| data | Any | 返回的结果数据,该数据可以是任何可序列化的格式,也可以是undefined |
开发者可以在项目里重写上下文对象的success和fail方法来修改返回数据格式,但由于框架内部也多次调用了这两个方法,因此不能修改这两个方法的参数顺序
参数配置功能依靠参数处理中间件koa-ajv-parser实现,该中间件遵循JSON Schema规范,因此开发者可以根据该规范来校验请求方传入的参数。
该中间件在校验失败时会直接返回一个错误给请求方,并且不再执行接口逻辑。而在校验成功时,则会把校验和处理后的参数存入到Context.state.params对象下的同名变量中供接口逻辑取用。
为了方便使用,params还支持一些JSON Schema规范外的特殊规则。具体如下:
- 仅在params对象下,属性可以用name:'type'的形式简写
- 仅在params对象下,会对type为object和array的参数执行JSON.parse之后再验证
- 仅在params对象下,所有属性默认都会设为required,除非设置了默认值或者optional:true
IP限制功能依靠KOA中间件koa-ip来实现。该中间件支持包括通配符在内的多种IP匹配的方式,并在IP受限的情况下直接返回403错误给请求方。
开发者可以直接把IP限制的配置直接写在接口文件中,也可以在项目配置文件里事先定义好几套IP限制方案,然后在接口文件中通过访问Application.config来获取对应配置。在实践中,使用第二种方案通常更加灵活一些。
一个IP限制的例子:
'use strict';
module.exports = app => {
return {
ip: app.config.ipWhiteList.self, // ['127.0.0.1']
controller:'yourController'
};
};注意:在服务器有前置代理的情况下,必须要把配置里的app.config.proxy设置为true才能正确的限制IP
结果缓存功能提供了 在请求成功后 把请求结果存入缓存,使一段时间内的同样的请求可以不再执行完整业务逻辑而直接从缓存返回执行结果的功能。结果缓存功能依靠插件egg-cache-9来实现,因此开发者在使用结果缓存功能之前必须确保已经正确配置缓存,具体配置方法详见进阶功能里的缓存一节。
结果缓存的配置采用逐字段合并的方法,优先使用接口文件上的配置,其次使用app.config.apiCache的配置,两者都没有配置的情况下使用默认配置。配置对象除了普通的缓存配置参数(如ttl)以外,还有两个额外的参数:
- cache:一个字符串,用于指定使用的缓存库的名字。若省略该参数,则默认使用名为http的缓存库,若没有对应还存库则会报错
- ctxKey(ctx) => ctx.path:一个方法,该方法用于计算缓存的键值。计算出相同键值的请求视为应该返回同样的结果
一个使用结果缓存的例子:
'use strict';
module.exports = app => {
return {
params: { key: 'string' },
cache: {
ctxKey: ctx => `${ctx.path}:${ctx.state.params.key}`,
},
controller:'yourController'
};
};注意:启用缓存可能导致数据不能实时更新,在使用缓存前必须先对接口做好评估
框架允许开发者把返回结果压缩之后返回给请求方,对于那些返回数据量巨大的接口,在这些接口上使用结果压缩可以显著的降低数据传输流量以缩短数据传输成本。结果压缩依靠中间件koa-compress实现,默认情况下该中间件使用gzip压缩结果数据。
压缩选项可以配置在接口文件中,也可以配置在app.config.compress里,接口会优先使用接口文件中的配置。
一个使用结果压缩的例子:
'use strict';
module.exports = app => {
return {
cache: {},
compress: true,
controller:'yourController'
};
};注意:由于使用结果压缩会稍微增加后端服务器的CPU压力,因此在条件允许的前提下,最好在启用结果压缩时同时启用结果缓存。