当前位置:网站首页 > iOS应用开发 > 正文

Web应用开发框架-egg(三)03-基础功能——中间件之编写中间件、中间件的配置、使用中间件、在框架和插件中使用中间件 & 中间件的通用配置项

Web应用开发框架-egg(三)03-基础功能——中间件之编写中间件、中间件的配置、使用中间件、在框架和插件中使用中间件 & 中间件的通用配置项

中间件

我们介绍了 Egg 是基于 Koa 实现的,所以 Egg 的中间件形式和 Koa 的中间件形式是一样的,都是基于洋葱圈模型。每次我们编写一个中间件,就相当于在洋葱外面包了一层。

编写中间件
// app/middleware/gzip.js const isJSON = require('koa-is-json'); const zlib = require('zlib'); async function gzip(ctx, next) { 
    await next(); // app.use过之后的下一个函数 // 后续中间件执行完成后将响应体转换成 gzip let body = ctx.body; if (!body) return; if (isJSON(body)) body = JSON.stringify(body); // 设置 gzip body,修正响应头 const stream = zlib.createGzip(); stream.end(body); ctx.body = stream; ctx.set('Content-Encoding', 'gzip'); } 
配置

一般来说中间件也会有自己的配置。在框架中,一个完整的中间件是包含了配置处理的。我们约定一个中间件是一个放置在 app/middleware 目录下的单独文件,它需要 exports 一个普通的 function,接受两个参数:

  • options: 中间件的配置项,框架会将 app.config[${middlewareName}] 传递进来。
  • app: 当前应用 Application 的实例。

我们将上面的 gzip 中间件做一个简单的优化,让它支持指定只有当 body 大于配置的 threshold 时才进行 gzip 压缩,我们要在 app/middleware 目录下新建一个文件 gzip.js

// app/middleware/gzip.js const isJSON = require('koa-is-json'); const zlib = require('zlib'); module.exports = options => { 
    return async function gzip(ctx, next) { 
    await next(); // 后续中间件执行完成后将响应体转换成 gzip let body = ctx.body; if (!body) return; // 支持 options.threshold if (options.threshold && ctx.length < options.threshold) return; if (isJSON(body)) body = JSON.stringify(body); // 设置 gzip body,修正响应头 const stream = zlib.createGzip(); stream.end(body); ctx.body = stream; ctx.set('Content-Encoding', 'gzip'); }; }; 
使用中间件

中间件编写完成后,我们还需要手动挂载,支持以下方式:

module.exports = { 
    // 配置需要的中间件,数组顺序即为中间件的加载顺序 middleware: [ 'gzip' ], // 配置 gzip 中间件的配置 gzip: { 
    threshold: 1024, // 小于 1k 的响应体不压缩 }, }; 
在框架和插件中使用中间件

可以通过app的config对象去个框架添加中间件,因为可能中间件执行顺序有一些要求。

// app.js module.exports = app => { 
    // 在中间件最前面统计请求时间 app.config.coreMiddleware.unshift('report'); }; // app/middleware/report.js module.exports = () => { 
    return async function (ctx, next) { 
    const startTime = Date.now(); await next(); // 上报请求时间 reportTime(Date.now() - startTime); } }; 

应用层定义的中间件(app.config.appMiddleware)和框架默认中间件(app.config.coreMiddleware)都会被加载器加载,并挂载到 app.middleware 上。

单个路由生效

中间件对象也挂载在app下面

module.exports = app => { 
    const gzip = app.middleware.gzip({ 
    threshold: 1024 }); app.router.get('/needgzip', gzip, app.controller.handler); }; 
框架默认中间件

除了应用层加载中间件之外,框架自身和其他的插件也会加载许多中间件。所有的这些自带中间件的配置项都通过在配置中修改中间件同名配置项进行修改,例如框架自带的中间件中有一个 bodyParser 中间件(框架的加载器会将文件名中的各种分隔符都修改成驼峰形式的变量名),我们想要修改 bodyParser 的配置,只需要在 config/config.default.js 中编写

module.exports = { 
    bodyParser: { 
    jsonLimit: '10mb', }, }; 
使用koa的中间件

以 koa-compress 为例,在 Koa 中使用时:

const koa = require('koa'); const compress = require('koa-compress'); const app = koa(); const options = { 
    threshold: 2048 }; app.use(compress(options)); 

我们按照框架的规范来在应用中加载这个 Koa 的中间件:

// app/middleware/compress.js // koa-compress 暴露的接口(`(options) => middleware`)和框架对中间件要求一致 module.exports = require('koa-compress'); 
// config/config.default.js module.exports = { middleware: [ 'compress' ], compress: { threshold: 2048, }, }; 

如果使用到的 Koa 中间件不符合入参规范,则可以自行处理下:

// config/config.default.js module.exports = { 
    webpack: { 
    compiler: { 
   }, others: { 
   }, }, }; // app/middleware/webpack.js const webpackMiddleware = require('some-koa-middleware'); module.exports = (options, app) => { 
    return webpackMiddleware(options.compiler, options.others); } 
通用配置

无论是应用层加载的中间件还是框架自带中间件,都支持几个通用的配置项:

  • enable:控制中间件是否开启。
  • match:设置只有符合某些规则的请求才会经过这个中间件。
  • ignore:设置符合某些规则的请求不经过这个中间件。

如果我们的应用并不需要默认的 bodyParser 中间件来进行请求体的解析,此时我们可以通过配置 enable 为 false 来关闭它

module.exports = { 
    bodyParser: { 
    enable: false, }, }; 

如果我们想让 gzip 只针对 /static 前缀开头的 url 请求开启,我们可以配置 match 选项

module.exports = { 
    gzip: { 
    match: '/static', }, }; 

match 和 ignore 支持多种类型的配置方式

  1. 字符串:当参数为字符串类型时,配置的是一个 url 的路径前缀,所有以配置的字符串作为前缀的 url 都会匹配上。 当然,你也可以直接使用字符串数组。
  2. 正则:当参数为正则时,直接匹配满足正则验证的 url 的路径。
  3. 函数:当参数为一个函数时,会将请求上下文传递给这个函数,最终取函数返回的结果(true/false)来判断是否匹配。
module.exports = { 
    gzip: { 
    match(ctx) { 
    // 只有 ios 设备才开启 const reg = /iphone|ipad|ipod/i; return reg.test(ctx.get('user-agent')); }, }, }; 
到此这篇Web应用开发框架-egg(三)03-基础功能——中间件之编写中间件、中间件的配置、使用中间件、在框架和插件中使用中间件 & 中间件的通用配置项的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • Web应用开发框架-egg(三)04-基础功能——路由之定义Router、restful风格的URL定义、获取路由参数2024-11-29 21:18:06
  • Web应用开发框架-egg(三)06-基础功能——插件之定义插件、编写插件 & 定时任务 & 自定义启动app2024-11-29 21:18:06
  • Web应用开发框架-egg(四)——egg总结之egg快速入门、内置对象、运行环境、config配置、中间件、路由、控制器、服务service、插件、定时任务、自定义启动2024-11-29 21:18:06
  • Web应用开发框架-egg进阶与实战(一)——debug调试步骤、日志之日志路径、日志分类、日志级别、如何打印日志、文件日志级别、日志切割、日志影响性能2024-11-29 21:18:06
  • Web应用开发框架-egg进阶与实战(三)——总结之debug、日志、多进程、错误处理、多实例插件、多进程增强、实战-简易博客2024-11-29 21:18:06
  • Web应用开发框架-egg(三)02-基础功能——运行环境 & Config配置之多环境配置、配置写法、配置加载顺序、合并规则、配置结果2024-11-29 21:18:06
  • Web应用开发框架-egg(三)01-基础功能——目录结构的约定之框架规定的目录、内置插件约定的目录 & 内置对象之Application、context、Request & Response等2024-11-29 21:18:06
  • Web应用开发框架-egg(二)——快速入门之模板渲染、编写helper扩展、编写Middleware、渐进式开发 & egg总结2024-11-29 21:18:06
  • Web应用开发框架-egg(一)——Egg入门、Egg与Koa的关系 & 快速入门之编写Controller、静态资源2024-11-29 21:18:06
  • Web应用开发框架-koa(五)——koa总结之koa特点、koa-route路由 & 中间件之洋葱模型、异步中间件、中间件的合成 & 错误处理之http状态码、koa抛出错误、错误处理中间件2024-11-29 21:18:06
  • 全屏图片