Home > Blockchain >  Can a middleware return middlewares in Express
Can a middleware return middlewares in Express

Time:11-30

I'm trying to combine different middlewares (multer and auth0 here) together to lower code complexity. Can I write one middleware that returns either middlewares or just next() (if the environment/parameters don't require its execution).

Something like this:

const constraints = {
    'local': {
        'GET': {},
        'POST': {
            'skills': {
                secured: true,
                upload: true,
                geolocation: false,
                illustrations: true,
                schema: skillsSchema
            },
            'donations': {
                secured: true,
                upload: true,
                geolocation: true,
                illustrations: false,
                schema: donationsSchema
            }
        }
    },
}

Should I return next ? or next() ? or true

function middleware(req, res, next) {
    const section = req.params[0]
    const method = req.method
    const { body } = req
    const {
        secured,
        upload,
        geolocation,
        illustrations,
        schema
    } = constraints[process.env.NODE_ENV][method][section];
    // Should I return next ? or next() ? or true
    const uploading = !upload ? next() : ops.multer
    const securing = !secured ? next() : ops.auth0
    const geoValid = !geolocation ? true : new PipeLine({
        point: {
            lat: body.lat,
            lng: body.lng
        }
    })
    .isPointInsidePolygon(coordinates)
    const undrawValid = !illustrations ? true : new PipeLine({
        body: body
    }).undrawSplit().joiValidate(schema).undrawJoin()
    res.locals.magicPipeLine = { geoValid, undrawValid }
    return [uploading, securing]
}

The route would be:

router.post(/^\/(donations|skills|blogs)/,
  middleware,
  async (req, res, next) => {

CodePudding user response:

You cannot return middleware from middleware, but you can return an array of middleware and use the spread operator.

const items = [middleware1, middleware2, (req, res, next)=>{ next() }]

app.get('/foo', ...items)

You also can call middleware from middleware.

  1. You should not call next() if your encapsulated middleware calls it. You should invoke the middleware manually if you want to integrate it in yours, and send it the next value (not call it). Here is an example: Calling a middleware from within a middleware in NodeJS/ExpressJS

  2. Returning values from middleware will not affect the flow at all.

CodePudding user response:

The middleware state logic in Express.js is about working on request and response parameters in a sequential way.

You should be doing stuff with the request parameters (params, query, body etc.) and then assigning it to a namespace can be used in next() function.

My bare-minimal authorization flow is something like this.

const authenticate = (roles) => (req, res, next) => {
  try {
    const { usr, rol, exp } = decode(req.headers.authorization, process.env.JWT_SECRET);
    if (exp > new Date().getTime()) {
      if (roles === 'all' || roles.includes(rol)) {
        req.user = usr;
        next();
      } else res.status(401).send('Wrong user type.');
    } else res.status(401).send('Expired token');
  } catch (e) { res.status(401).send('You need a token.'); }
};

As you'll see I'm payloading body with the "processed" authentication header.

You should return next() in your middlewares.

  • Related