Flexible use of middleware
mechanism can effectively extend the functions of the architecture. The main effects of middleware are interception
and restructuring
- interception: For example, judging user privileges through middleware and suspending subsequent execution if no privileges exist
- restructuring: For example, the data sent from the frontend is validated by middleware and transformed into the desired type
Here, through a virtual requirement, we use middleware to achieve the effects of interception
and restructuring
:
- Requirement: The frontend sends two parameters:
a
andb
, and the backend calculates thesum
of them and returns them to the frontend - interception: The middleware judges whether the parameters are
undefined
. If they areundefined
, subsequent execution will be aborted - restructuring: Cast parameters type to
Integer
Create Middleware
1. Declaration of Middleware
src/suite-vendor/test-party/modules/test-party/backend/src/config/config.js
- 1// middlewares
- 2config.middlewares = {
- 3 testInterception: {
- 4 bean: 'testInterception',
- 5 global: false,
- 6 dependencies: 'instance',
- 7 },
- 8 testRestructuring: {
- 9 bean: 'testRestructuring',
- 10 global: false,
- 11 dependencies: 'instance',
- 12 },
- 13};
名称 | 说明 |
---|---|
bean | The bean component name used to implement middleware logic |
global | Whether global middleware or not, the global middleware will be loaded automatically, and the local middleware needs to be specified on the API route manually |
dependencies | Indicate which middlewares this middleware relies on to load after those middlewares. Generally, it depends on middleware instance , because middleware instance provides the basic logic of multi-instance |
2. Definition of Middleware Bean Component
src/suite-vendor/test-party/modules/test-party/backend/src/bean/middleware.interception.js
- 1module.exports = ctx => {
- 2 class Middleware {
- 3 async execute(options, next) {
- 4 const { a, b } = ctx.request.body;
- 5 if (a === undefined || b === undefined) return ctx.throw(1002); // 1002: 'Incomplete Parameters'
- 6 // next
- 7 await next();
- 8 }
- 9 }
- 10 return Middleware;
- 11};
src/suite-vendor/test-party/modules/test-party/backend/src/bean/middleware.restructuring.js
- 1module.exports = ctx => {
- 2 class Middleware {
- 3 async execute(options, next) {
- 4 const { a, b } = ctx.request.body;
- 5 ctx.request.body.a = parseInt(a);
- 6 ctx.request.body.b = parseInt(b);
- 7 // next
- 8 await next();
- 9 }
- 10 }
- 11 return Middleware;
- 12};
3. Register Middleware Bean Component
src/suite-vendor/test-party/modules/test-party/backend/src/beans.js
- 1const middlewareTestInterception = require('./bean/middleware.interception.js');
- 2const middlewareTestRestructuring = require('./bean/middleware.restructuring.js');
- 3
- 4module.exports = app => {
- 5 const beans = {
- 6 // middleware
- 7 'middleware.testInterception': {
- 8 mode: 'ctx',
- 9 bean: middlewareTestInterception,
- 10 },
- 11 'middleware.testRestructuring': {
- 12 mode: 'ctx',
- 13 bean: middlewareTestRestructuring,
- 14 },
- 15 };
- 16 return beans;
- 17};
Usage of Middleware
1. Config API Route
Because testInterception
and testRestructuring
are local middlewares, you need to specify it manually on the API route
src/suite-vendor/test-party/modules/test-party/backend/src/routes.js
- 1// test/feat/middleware
- 2{ method: 'post', path: 'test/feat/middleware/interception', controller: 'testFeatMiddleware', middlewares: 'test,testInterception' },
- 3{ method: 'post', path: 'test/feat/middleware/restructuring', controller: 'testFeatMiddleware', middlewares: 'test,testInterception,testRestructuring' },
2. Backend Logic
src/suite-vendor/test-party/modules/test-party/backend/src/controller/test/feat/middleware.js
- 1module.exports = app => {
- 2
- 3 class TestController extends app.Controller {
- 4
- 5 async interception() {
- 6 const { a, b } = this.ctx.request.body;
- 7 const c = parseInt(a) + parseInt(b);
- 8 this.ctx.success(c);
- 9 }
- 10
- 11 async restructuring() {
- 12 const { a, b } = this.ctx.request.body;
- 13 const c = a + b;
- 14 this.ctx.success(c);
- 15 }
- 16
- 17 }
- 18
- 19 return TestController;
- 20};
src/suite-vendor/test-party/modules/test-party/backend/src/controllers.js
- 1const testFeatMiddleware = require('./controller/test/feat/middleware.js');
- 2
- 3module.exports = app => {
- 4 const controllers = {
- 5 testFeatMiddleware,
- 6 };
- 7 return controllers;
- 8};
Unit-Test
Here, we use unit-tests
to verify that the middleware mechanism works as expected
src/suite-vendor/test-party/modules/test-party/backend/test/controller/test/feat/middleware.test.js
- 1const { app, mockUrl, mockInfo, assert } = require('egg-born-mock')(__dirname);
- 2
- 3describe('test/controller/test/feat/middleware.test.js', () => {
- 4
- 5 it('action:interception', async () => {
- 6 // success
- 7 let result = await app.httpRequest()
- 8 .post(mockUrl('test/feat/middleware/interception'))
- 9 .send({
- 10 a: '1',
- 11 b: '2',
- 12 });
- 13 assert.equal(result.body.data, 3);
- 14
- 15 // fail
- 16 result = await app.httpRequest()
- 17 .post(mockUrl('test/feat/middleware/interception'))
- 18 .send();
- 19 assert.equal(result.status, 500);
- 20 });
- 21
- 22 it('action:restructuring', async () => {
- 23 // success
- 24 const result = await app.httpRequest()
- 25 .post(mockUrl('test/feat/middleware/restructuring'))
- 26 .send({
- 27 a: '1',
- 28 b: '2',
- 29 });
- 30 assert.equal(result.body.data, 3);
- 31 });
- 32
- 33});
Comments: