Home > front end >  Calling third party middlewares inside a custom middleware in NodeJS Express
Calling third party middlewares inside a custom middleware in NodeJS Express

Time:04-09

I'm learning NodesJS Express. I am using Express-Validator for my testing purposes. Here is my testing program.

const express = require("express");
const app = express();
const port = 5000;
let bodyParser = require("body-parser");

const { body, validationResult } = require("express-validator");

app.use(express.json());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.post(
  "/user",
  body("username").isEmail(),
  body("password").isLength({ min: 5 }),
  (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
    console.log("Login successfully!");
    res.send(200);
  }
);

app.listen(port, () => {
  console.log(`Server is listening on port ${port}`);
});

When I tried to use a post request with the body parameter: { username:test@, password:12345a }, it worked as my expectation. The server will response like this:

response

The problem happened when I tried to wrap all the logic in the post request handler into a single middleware. When I sent the same post request, it didn't show the error like the example above. That means the two express-validator donot work. Here is my new program.

const express = require("express");
const app = express();
const port = 5000;
let bodyParser = require("body-parser");

const { body, validationResult } = require("express-validator");

app.use(express.json());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

const validateEmailAndPwdlength = (req, res, next) => {
  body("username").isEmail(); // the express-validator middleware doesn't work here.
  body("password").isLength({ min: 5 });  // the express-validator middleware doesn't work here.
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }
  console.log("Login successfully!");
  res.sendStatus(200);
};

app.post(
  "/user",
  validateEmailAndPwdlength
);

app.listen(port, () => {
  console.log(`Server is listening on port ${port}`);
});

The two express-validator body("username").isEmail() and body("password").isLength({ min: 5 }) are the validation chains. From Express-Validator document, it says that 'The validation chain is a middleware, and it should be passed to an Express route handler'. Why should we place them a Express route handler? If not, how can we call them inside my second example?

Thank you so much for your time!

CodePudding user response:

body("username").isEmail() evaluates to a function, and if you simply put it as a statement in your validateEmailAndPwdlength, it has no effect at all. You could invoke the function yourself, as in (simplified)

const validateEmailAndPwdlength = (req, res, next) => {
  body("username").isEmail()(req, res, function() {
    body("password").isLength({min: 5})(req, res, function() {
      const errors = validationResult(req);
      ...
    });
  });
}

but that is much longer and less readable (even in this simplified version) than your first version where you follow the express-validator's advice. It's so much more elegant, what don't you like about it?

Addendum: You can see in the Node.js console that the validation chains are actually functions:

> body("username").isEmail().toString()
'async (req, _res, next) => {\n'  
  '        try {\n'  
  '            await runner.run(req);\n'  
  '            next();\n'  
  '        }\n'  
  '        catch (e) {\n'  
  '            next(e);\n'  
  '        }\n'  
  '    }'
  • Related