Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

honion

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

honion

通用洋葱模型中间件

  • 0.0.1
  • Source
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

Honion - 通用洋葱模型中间件

GitHub license npm version npm downloads node compatibility Build Status Test Coverage PRs Welcome Gitpod Ready-to-Code

🌈 介绍

Honion 是一个通用的洋葱模型中间件,扩展性强

适用于各类项目,将复杂逻辑分步骤简单化、条理化

中间件的功能包括:

  • 执行代码
  • 修改请求和响应对象
  • 拦截请求
  • 调用下一个中间件

示例代码均为 TypeScript,可自行替换为 JavaScript

执行顺序

Honion 的中间件使用了洋葱模型,即按以下顺序执行各中间件

  • 进入中间件并执行代码
  • 执行下一个中间件
  • 执行剩余代码
  • 返回上一个中间件

如果没有执行下一个中间件,请求会沿当前中间件直接返回上一个中间件

中间件类型

有两种中间件

  • 类中间件
  • 函数式中间件

如果中间件代码较多,建议使用类中间件,让代码更易读

函数式中间件最终会被转换为类中间件执行,但你可能无需关注这个特点

类中间件和函数式中间件使用方式不同,但都大同小异

中间件执行的顺序严格遵循添加顺序

🎉 开始使用

先创建一个中间件容器,继承 Honion 类,在合适的位置调用 this.invoke() 即开始执行各中间件

一般情况你还需要重写 invoke() 函数,以自定义初始化 Context 对象

class TestHonion extends Honion {
  // custom function
  async run() {
    const ctx = await this.invoke();
    // do some work
  }

  // override
  protected async invoke(ctx: Context): Promise<Context> {
    // init ctx
    return await super.invoke(ctx);
  }
}

实例化中间件容器后,即可在中间件容器中增加中间件

const honion = new TestHonion()
  .use(async (ctx, next) => {
    // do some work before next middleware
    await next();
    // do some work after next middleware
  })
  .use(async (ctx, next) => {
    // do some work
  });

await honion.run();
函数式中间件

通过 honion.use() 添加

honion
  .use(async (ctx, next)=>{
    ctx.res.setHeader("h1", 1);
    await next();
    ctx.res.setHeader("h3", 3);
  })
  .use((ctx)=>{
    ctx.res.setHeader("h2", 2);
  })
类中间件

通过 honion.add() 添加

创建一个类,并继承 Middleware,实现 invoke 函数

class TestMiddleware extends Middleware{
  async invoke(){
    this.ctx.res.setHeader("h1",1);
    await this.next();
    this.ctx.res.setHeader("h2",2);
  }
}
honion.add(TestMiddleware) // 一般中间件
// OR
honion.add(new TestMiddleware()) // 不推荐
// OR
honion.add(async (ctx) => TestMiddleware) // 动态中间件
// OR
honion.add(async (ctx) => new TestMiddleware()) // 动态中间件并自行实例化
组合中间件

ComposeMiddleware 中间件可以组合多个中间件

这些中间件形成的中间件管道,会与主中间件管道相连接

支持多层嵌套组合

该类的成员函数 adduseHonion 类用法相同

honion
  .use(async (ctx, next) => {
    await next();
  })
  .add(() =>
    new ComposeMiddleware()
      .use(async (ctx, next) => {
        await next();
      })
      .add(() =>
        new ComposeMiddleware()
          .use(async (ctx, next) => {
            await next();
          })
          .add(() =>
            new ComposeMiddleware()
              .use(async (ctx, next) => {
                await next();
              })
              .use(async (ctx, next) => {
                await next();
              })
          )
          .use(async (ctx, next) => {
            await next();
          })
      )
      .use(async (ctx, next) => {
        await next();
      })
  )
  .use(async (ctx, next) => {
    await next();
  });

中间件钩子

中间件钩子可以在中间件的不同生命周期,运行指定的代码

  • 钩子本质也会被转换为中间件
  • 钩子只会作用于其后的中间件
honion.hook(HookType, (ctx, md) => {})

该函数有两个参数

  1. 钩子类型,有以下几种钩子
    • BeforeInvoke:在中间件执行之前执行,默认参数。若返回 false 则终止后续同类型钩子执行,并且不执行当前中间件
    • AfterInvoke:在中间件执行之后执行,即 next 之后
    • BeforeNext:在中间件 next 执行前执行,如果在中间件中没有调用 next,将不触发这种钩子,若返回 false 则终止后续同类型钩子执行,并且不执行下一个中间件
    • Constructor:用于构造中间件,利用这种钩子可以动态使用中间件。但注册的中间件,必须是中间件的构造器,即 honion.add(YourMiddleware) 的方式
    • Error:中间件抛出异常时会执行这类钩子
  2. 钩子回调函数,有两个或三个参数
    • 参数 1:管道 Context 对象
    • 参数 2:中间件对象或中间件构造函数
      • 如果钩子类型为 Constructor,则参数为中间件构造函数
      • 如果钩子类型为 Error,则参数为 Error 对象或其派生对象
      • 如果钩子类型为 BeforeInvokeAfterInvokeBeforeNext,则参数为中间件对象
    • 参数 3: 如果钩子类型为 Error,则此参数为 Error 对象,否则无此参数
    • 返回值:
      • 如果钩子类型为 Constructor,则需要返回中间件对象
      • 如果钩子类型为 Error,则返回值为 bool 类型
        • 返回 true 说明在钩子函数中已处理异常,不会执行下一个异常钩子
        • 返回 false 说明在钩子函数中未处理异常,会继续执行下一个异常钩子
      • 如果钩子类型为 BeforeInvokeAfterInvokeBeforeNext,则没有返回值

其中参数 1 可省略,默认为 BeforeInvoke

  import { Middleware } from "honion";

honion
    .hook((md) => {
      // 1 before hook
      if (md instanceof TestMiddleware) {
        md.count++;
      }
    })
    .add(TestMiddleware)
    .hook((md) => {
      // 2 before hook
      if (md instanceof TestMiddleware) {
        md.count++;
      }
    })
    .add(TestMiddleware)
    .hook((md) => {
      // 3 before hook
      if (md instanceof TestMiddleware) {
        md.count++;
      }
    })
    .hook(HookType.AfterInvoke, (ctx, md) => {
      // AfterInvoke: executed but without effective
      if (md instanceof TestMiddleware) {
        md.count++;
      }
    })
    .hook(HookType.BeforeNext, (ctx, md) => {
      // BeforeNext: executed before next
      if (md instanceof TestMiddleware) {
        md.count++;
      }
    })
    .add(TestMiddleware)
    .use((ctx) => ctx.ok());

贡献

遇到问题

首先查找是否已有相关问题:

  1. 查看 Discussions 是否有相关讨论
  2. 查看 Issues 是否有相关内容

如果以上没有找到答案:

  • 一般性问题请在讨论区提问 Discussions
  • 代码问题或不符预期的行为请提 Issues

如果你能通过代码解决这个问题欢迎提交 Pull requests

License

MIT

Copyright (c) 2023-present, Hal Wang

Keywords

FAQs

Package last updated on 17 Feb 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc