tachybase_todo/docs/en-US/development/server/middleware.md
2022-11-06 13:48:06 +08:00

3.6 KiB

Middleware

How to register middleware?

The registration method for middleware is usually written in the load method

export class MyPlugin extends Plugin {
  load() {
    this.app.acl.use();
    this.app.resourcer.use();
    this.app.use();
  }
}

Notes.

  1. app.acl.use() Add a resource-permission-level middleware to be executed before permission determination
  2. app.resourcer.use() Adds a resource-level middleware that is executed only when a defined resource is requested
  3. app.use() Add an application-level middleware to be executed on every request

Onion Circle Model

app.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(1);
  await next();
  ctx.body.push(2);
});

app.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(3);
  await next();
  ctx.body.push(4);
});

Visit http://localhost:13000/api/hello to see that the browser responds with the following data

{"data": [1,3,4,2]}

Built-in middlewares and execution order

  1. cors
  2. bodyParser
  3. i18n
  4. dataWrapping
  5. db2resource 6.
  6. restApi 1.
    1. parseToken 2.
    2. checkRole
    3. acl 1.
      1. acl.use() Additional middleware added
    4. resourcer.use() Additional middleware added
    5. action handler
  7. app.use() Additional middleware added

You can also use before or after to insert the middleware into the location of one of the preceding tag, e.g.

app.use(m1, { tag: 'restApi' });
app.resourcer.use(m2, { tag: 'parseToken' });
app.resourcer.use(m3, { tag: 'checkRole' });
// m4 will come before m1
app.use(m4, { before: 'restApi' });
// m5 will be inserted between m2 and m3
app.resourcer.use(m5, { after: 'parseToken', before: 'checkRole' });

If no location is specifically specified, the order of execution of the added middlewares is

  1. middlewares added by acl.use will be executed first
  2. then the ones added by resourcer.use, including the middleware handler and action handler
  3. and finally the ones added by app.use
app.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(1);
  await next();
  ctx.body.push(2);
});

app.resourcer.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(3);
  await next();
  ctx.body.push(4);
});

app.acl.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(5);
  await next();
  ctx.body.push(6);
});

app.resourcer.define({
  name: 'test',
  actions: {
    async list(ctx, next) {
      ctx.body = ctx.body || [];
      ctx.body.push(7);
      await next();
      ctx.body.push(8);
    },
  },
});

Visit http://localhost:13000/api/hello to see that the browser responds with the data

{"data": [1,2]}

Visiting http://localhost:13000/api/test:list to see, the browser responds with the following data

{"data": [5,3,7,1,2,8,4,6]}

Resource undefined, middlewares added by resourcer.use() will not be executed

app.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(1);
  await next();
  ctx.body.push(2);
});

app.resourcer.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(3);
  await next();
  ctx.body.push(4);
});

Visit http://localhost:13000/api/hello to see that the browser responds with the following data

{"data": [1,2]}

In the above example, the hello resource is not defined and will not enter the resourcer, so the middleware in the resourcer will not be executed

Middleware Usage

TODO

Example