使用titbit开发Web后端服务04:中间件执行机制
中间件
中间件是一个很有用的模式,不同语言实现起来多少还是有些区别的,但是本质上没有区别。中间件的运行机制允许开发者更好的组织代码,方便实现复杂的逻辑需求。事实上,整个框架的运行机制都是中间件模式。
titbit中间件执行机制是完全独立设计的,没有基于任何其他扩展,并且是支持分组和匹配请求类型和请求名称执行的,你可以添加上千个中间件,但是不同路由表示的不同功能可能仅仅需要执行几十个,各自独立不互相影响。而更方便的是,你可以通过titbit-loader扩展来实现自动编排和加载,实现集中管理。
![]()
示例
1 //先执行 2 app.use(async (c, next) => { 3 let start_time = Date.now() 4 await next() 5 let end_time = Date.now() 6 console.log(end_time - start_time) 7 }) 8 9 //后执行 10 app.use(async (c, next) => { 11 console.log(c.method, c.path) 12 await next() 13 }) 14 15 //use可以级联: app.use(m1).use(m2) 16 //在21.5.4版本以后,不过这个功能其实根本不重要 17 //因为有titbit-loader扩展,实现的功能要强大的多。
add和use
使用add添加的中间件是按照添加顺序逆序执行,这是标准的洋葱模型。为了提供容易理解的逻辑,提供use接口添加中间件,使用use添加的中间件按照添加顺序执行。不同的框架对实现顺序的逻辑往往会不同(比如,PHP的Slim框架实现的标准洋葱模型就是后添加先执行),但是顺序执行更符合开发者习惯。
1 /* 2 第二个参数可以不填写,表示全局开启中间件。 3 现在第二个参数表示:只对POST请求方法才会执行,并且路由分组必须是/api。 4 基于这样的设计,可以保证按需执行,不做太多无意义的操作。 5 */ 6 app.add(async (c, next) => { 7 console.log('before'); 8 await next(); 9 console.log('after'); 10 }, {method: 'POST', group: '/api'});
pre 在接收body数据之前
使用pre接口添加的中间件和use添加的主要区别就是会在接收body数据之前执行。可用于在接收数据之前的权限过滤操作。其参数和use一致。
为了一致的开发体验,你可以直接使用use接口,只需要在选项中通过pre指定:
1 let setbodysize = async (c, next) => { 2 //设定body最大接收数据为~10k。 3 c.maxBody = 10000; 4 await next(); 5 }; 6 7 //等效于app.pre(setbodysize); 8 app.use(setbodysize, {pre: true});
使用pre可以进行更复杂的处理,并且可以拦截并不执行下一层,比如titbit-toolkit扩展工具集中的 proxy模块 利用这个特性直接实现了高性能的代理服务,作为框架的一个中间件扩展可以更方便的结合各种组件实现非常灵活的web服务。其主要操作就是在这一层,直接设置了request的data事件来接收数据,并作其他处理,之后直接返回。
中间件参数
使用use或者pre接口添加中间件,还支持第二个参数,可以进行精确的控制,传递选项属性:
- group 路由分组,表示针对哪个分组执行。
- method 请求方法,可以是字符串或数组,必须大写。
- name 请求名称,表示只针对此请求执行。
示例:
1 app.get('/xyz', async c => { 2 //... 3 //路由分组命名为proxy 4 }, {group: 'proxy'}) 5 6 app.use(proxy, { 7 method : ['PUT', 'POST', 'GET', 'DELETE', 'OPTIONS'], 8 //针对路由分组proxy的请求执行。 9 group : 'proxy' 10 })
titbit完整的流程图示



浙公网安备 33010602011771号