ec-router
v1.2.0
Published
一个koa2自动路由中间件,直接根椐请求方法及路径路由到指定的controller。无需人工编写路由表或映射
Downloads
31
Maintainers
Readme
ec-router
一个简单易用的koa2路由中间件,提供规则路由功能,不再需要复杂无趣的路由文件,路由影射表等。
feature
koa2路由中间件
根椐请求方法及URI进行自动路由
控制器钩子,支持before,after,error
配置文件及控制器热重载
change log
如果你之前使用过ec-router,请注意新版本为了保持router的功能单一性,相对旧版本,作了比较大的简化,修改如下:
去掉了自动装载数据库进行自动RESTful的功能,如果你需要此功能,请参考本文档后面的使用例子自行实现。
增加_any控制器,处理无法匹配的的resource
在hook中增加error方法,处理路由过程抛出的错误
默认的控制器方法名称由all改为_any
将resource、resourceId和action注入到 ctx.ecRouter
install
npm install ec-router --save
npm test
也可从 git仓库 中下载源码,放到你项目的node_modules目录
URI格式说明
http://domain[:port]/[prefix]/[apiver]/path
[prefix] : 表示路径前缀(可为空),可在config中设置
[apiver] : 表示api的版本,在config中设置 apiVer 为true时生效, 版本规则由apiVeRegex定义,默认规则为两位版本号,比如v1.0,v11,v2,11,12.22
path : 为具体资源路径,根椐不同的路由类型有不同
ec-router根椐请求的方法、路径或查询参数,自动分析得出controller(resource)和action,再调用相应的方法来处理。
如果对应的controller没有找到,会在controllers目录查找_any.js来代替(使用者可在此控制器内用_any方法来实现自动处理RESTful请求)
如果对应的action没有找到,则查找_any方法代替。
如果都找不到,则抛出异常,进入_hook的error方法处理(如果有的话)
route type
type=1, RESTful方式
本方式使用RESTful访问,根椐请求方法和请求的资源名称、ID来处理,比如:
GET /res/12 // => controller=res,method=get
POST /User // => controller=user,method=post
PUT /user/11 // => controller=user,method=put
其中的"res"和"user"表示资源名称
type=2,Path方式
本方式根椐路径匹配控制器和控制器方法, path的格式为: /controller/action
如:
/res/list // => controller=res, method=list
/user/add // => controller=user, method=add
/user // => controller=user, method=any
该方式不区分请求方法,可在实现控制器时根椐需求自行判断
type=3,QueryString方式
本方式使用请求字符串进行路由判断,比如:/apiName?c=controller&a=action,查找controller及action的方式同type=2
(其中c,a为参数名称,可在config中修改)
如:
/index?c=user&a=list // => controller=uer, method=list
/index?c=user&a=add // => controller=user, method=add
/index?c=user&a= // => controller=user, method=any
此方法同样不区分请求方法,可在实现控制器时根椐需求自行判断
Usage
koa app main
//index.js
const Koa = require('koa')
const app = new Koa()
const ecRouter = require('ec-router')
process.env.NODE_ENV = 'dev' //开启debug log
//加载其它中间件
//如果需要自动RESTful服务,需要使用bodyParser之类的请求内容解释中间件来预处理请求参数
app.use(bodyParser())
//修改ec-router的默认配置
ecRouter.loadConfig(__dirname+'/ec-config.js')
app.use(ecRouter.dispatcher())
//use other middleware
app.listen(3000)
热加载
当在配置文件中设置了hotLoad=true(缺省值)时,ec-router支持配置文件及controller的热加载(hotLoad配置的修改不支持热更新)
如果需要使用热加载,请将配置独立成模块,再使用 ecRouter.loadConfig('./config.js')
代替 ecRouter.setConfig(conf)
controller
ec-router通过dispatch将不同的请求路由到不同的控制器方法,默认地,需要将控制器文件放置在APP根目录下的controllers目录(可在配置中修改)
控制器文件名、控制器方法、资源名称等大小写敏感
控制器方法的函数原型是 async (ctx) =>{}
type=1时,使用get,post,put,delete来命名对应的控制器方法,type非1时,可以自行定义(对应path或querystring中的action命称),可以定义_any方法来适配不存在的方法。
// controllers/user.js
module.exports = {
get : async (ctx) => {
//ctx.req.resourceId //effective when type=1,
//ctx.req.resource
ctx.body = "get User"
},
post: async (ctx) => {
ctx.body = "post user"
},
//当action无法匹配以上方法时,会自动匹配为此方法
_any: async (ctx) => {
//other method
}
}
api version
对于是否应该在URI中添加api的version,不同的人有不同的看法,ec-router建议的方式在你需要版本控制时,在URI中添加。
- 配置中设置 apiVer为true
- 需在controllers目录下创建版本目录,并将控制文件放到相应的版本目录,如 : 路径/v1/res,会路由到 controllers/v1/res.js。
如果你希望使用Accept的media type或其它header来控制版本,可以在_any控制器的_any方法中,判断并依靠获得的版本号及注入到ctx.ecRouter的resource,action来require相应版本的控制器
通用controller
通用controller需要使用者自行定义并放置在controller目录,该节说明通用控制器的用途及实现方法。
before和after钩子
如果需要在每个控制器方法执行之前或之行都执行一些逻辑,可以使用钩子,方法是:
- 在 controllers目录下放置控制器钩子,文件名为 _hook.js
- 在_hook.js中实现并导出before或after方法(可同时或单独前后添加钩子),方法原型与普通controller方法一样
module.exports = {
//do before all controller action
before : async (ctx) => {
ctx.set("Access-Control-Allow-Origin", "*")
ctx.set("Access-Control-Allow-Headers", "Origin, Content-Type")
},
//do after all controller action
after: async (ctx) => {
console.log('controller finish')
},
//路由时抛错的处理
error: async(ctx,err) =>{
}
}
注意:只有控制器能正常执行,before和after才能被执行,如果在调用控制器之前抛错或返回了,before和after也不会执行。
默认控制器
当找不到指定的controller时,ec-router会去查找controller目录下的_any.js作为默认控制器。
使用该特性,可以实现自动的RESTful服务:
//_any.js
module.exports = {
get : async (ctx) => {
//根椐ctx.ecRouter.resource ,ctx.ecRouter.resourceId及其它query参数自动从数据库获取内容输出
},
post: async (ctx) => {
//实现更新数据
},
}
错误控制器
在碰到无法正常处理的请求时,ec-router会抛出异常,并在最后catch这些异常,传递给_hook.js控制器的error方法处理(如果没有则只输出到控制台)
config
可以在调用ec-router.dispatcher之前使用loadConfig来修改默认配置(config文件只需定义不使用默认值的项)
{
type : 1, //路由方式
uriApiName : 'index', //使用querystring方式时,指定API文件名,即/apiName?c=xx&m=xx
uriCParam : 'c', //使用querystring方式时,指定控制器的参数名
uriAParam : 'a', //使用querystring方式时,指定控制器方法的参数名
uriPrefix : '', //API路径前缀,如: /prefix/controller/action
uriDefault : '/index', //默认uri path
apiVer : false, //是否支持版本声明
apiVeRegex : /^v?(\d){1,2}(\.[\d]{1,2})?$/, //版本规则,
controllerPath : 'controllers', //控制器文件所在目录,相对于app根目录
allowMethod : ['get','post','put','delete','options'] //允许的请求方法
}
数据访问
ec-router并不包括数据访问的处理,以下只是一些建议:
- 通过koa的middleware,建立一个数据连接的中间件,建立和获取连接,并将连接句柄注入为ctx.dbconn,然后可以在controller中使用
- 通过_hook的before建立数据连接获取,注入ctx.dbconn
- 建立dao基类,然后在其之上实现各对象的dao,直接使用dao调用
License
MIT is open-sourced software licensed under the MIT license.