DEV Community

Discussion on: Joi — awesome code validation for Node.js and Express

Collapse
 
dmitrye profile image
Dmitry Erman • Edited

Great Article Chris. Covers something I've had in my code for a while. There is one more feature that you're not covering.

Joi returns sanitized values of parameters in a 2nd parameter. For example, you can have Joi validate (truthy, falsy, etc) that 'false', false, 0, and 'N' are all equivalent to false for your filter=N query parameter. It will then return false as a boolean. By default all query parameters come through as strings.

To apply the above to your code you would do something like this to manipulate the request object with the sanitized version of the objects:

const middleware = (schema, property) => { 
  return (req, res, next) => { 
  const { error, values } = Joi.validate(req[property], schema); 
  const valid = error == null; 

  if (valid) { 

    /**
    * Manipulate the existing request object with sanitized versions from Joi. This is an example
    * and I'm sure there are other and more efficient ways.
   **/
    if(value && Object.keys(value).length > 0){
        for(const prop in value){

          //maybe not necessary, but defensive coding all the way.
          if(value.hasOwnProperty(prop)){
            if(req.query && req.query[prop]){
              req.query[prop] = value[prop];
            }

            if(req.body && req.body[prop]) {
              req.body[prop] = value[prop];
            }

            if(req.params && req.params[prop]) {
              req.params[prop] = value[prop];
            }
          }
        }
      }
    next(); 
  } else { 
    const { details } = error; 
    const message = details.map(i => i.message).join(',');

    console.log("error", message); 
   res.status(422).json({ error: message }) } 
  } 
} 

You can also append the values object to req.options = values that would allow you to have both. But then your code will need to know which one to grab.