1

I'm trying to create a module for my validation requests of req.body.

instead of adding the following piece of code to every request to the server, I want to just add it to a module and do it in a one-line code.

const errors = validationResult(req);
  if (!errors.isEmpty()) {   
   return res.status(400).json({ errors: errors.array() });
  }

So I have put this code in validation.js:

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

// Finds the validation errors in this request and wraps them in an object with handy functions
const checkForErrors = (req, res, next) => {
  console.log("hello");
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }
};

module.exports = checkForErrors;

and this in app.js:

const checkForErrors = require("../config/validation");

// get /business/biz/:id page
router.get(
  "/biz/:id",
  [param("id").isAlphanumeric().trim()],
  (req, res) => {
    checkForErrors(req,res);
    bizID = req.params.id;
    console.log(bizID);
    res.send("Hello Business biz single page ");
  }
);

But when I do this and there is an error I get Error can't send headers after they are sent.

How can I make sure that if there is an error the response stops in validation.js? Thanks in advance.

Mendi Sterenfeld
  • 378
  • 5
  • 26

1 Answers1

1

checkForErrors is already defined as a middleware function, which allows you to put it in the middleware chain for your route-handler, e.g.

router.get(
  "/biz/:id",
  [param("id").isAlphanumeric().trim()],
  checkForErrors,
  (req, res) => {
      bizID = req.params.id;
      console.log(bizID);
      res.send("Hello Business biz single page ");
  }
);

The only thing you need to change is to call next within checkForErrors in case there's no error:

//...
const errors = validationResult(req);
if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
}
next();

EDIT for a more reusable solution with error handling:

// create a new error class
class ValidationError extends Error {
   constructor(errors) {
      super("Validation error occurred");
      this.errors = errors;
   }
}

// throw ValidationError in case of validation errors
const checkForErrors = (req) => {
  console.log("hello");
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    throw new ValidationError(errors.array());
  }
};

// call the function inside your handler callback
router.get(
  "/biz/:id", ...  
  (req, res) => {
    checkForErrors(req);
    bizID = req.params.id;
    console.log(bizID);
    res.send("Hello Business biz single page ");
  }
);

// add a global error handling middleware and handle validation error there
app.use((err, req, res, next) => {
  if(err instanceof ValidationError) {
    return res.status(400).json({ errors: err.errors });
  }
  console.error(err.stack)
  res.status(500).send('Some unexpected error occurred!')
})
eol
  • 23,236
  • 5
  • 46
  • 64
  • Thanks, but I'm looking to put it inside the arrow function. (for future functions where I don't want to put it in the middleware) – Mendi Sterenfeld Jul 27 '20 at 16:14
  • I would change the logic in that case - throw an error inside your check if there's a validation error and use a global error-middleware to handle this error. I'll edit my answer. – eol Jul 27 '20 at 21:28
  • I followed your steps and split it into 3 files. the `class` and `checkForErrors` function I put in `validation.js`. the `checkForErrors(req)` in `admin.js` and the error handler in `app.js`. but if I get a validation error i get the following error in the console: `UnhandledPromiseRejectionWarning: Error: Validation error occurred` and no response from the server to the client. – Mendi Sterenfeld Jul 28 '20 at 14:05
  • Are you dealing with async-operations inside your request-handler? If yes, you might want to check out this link: https://stackoverflow.com/questions/51391080/handling-errors-in-express-async-middleware – eol Jul 28 '20 at 14:46
  • thanks for the tip, but for some reason I couldn't implement that. – Mendi Sterenfeld Jul 28 '20 at 17:14