brandonscript
brandonscript

Reputation: 72965

Using node-validator to validate multiple properties at once

I'm building a Node.js proxy with the intent of handling a single POST request and redirecting the payload to two separate endpoints.

Let's say my JSON payload is:

{
  "owner":"0ce856fa-f17f-11e2-9062-9b7910849bf4",
  "comment":"My super cool comment!",
  "photo":"0928536a-53c4-11e3-ba86-4b026f27c637"
}

I need to validate this payload on the proxy endpoint before I send it off; each of these three properties must exist, and both owner and photo must match the regex below. If they don't pass validation, I need to handle the error(s) and return a message back to the user with an appropriate error code.

I've set up a basic Node.js instance with Express and Validator like so in order to accomplish this:

var url = require('url');
var request = require('request');
var express = require('express');
var check = require('validator').check,
    sanitize = require('validator').sanitize;

var app = express();

app.use(express.json());
app.use(express.urlencoded());

app.all('*', function(req, res){
    if (req.method == "POST")
    {
        try {
            check(req.body.owner, {
                is: "<owner> property of type [uuid] is required"
            }).is(/\w{8}(?:-\w{4}){3}-\w{12}?/);
        } catch (e) {
            console.log(e);
            res.json({"result":"failed","message":"Your payload didn't pass validation"});
        }
    }
});

app.listen(9000, function() {
    console.log("Server initialized on port 9000");
});

The problem: this is all fine and dandy and works great for a single validation (in this case owner), but e on catch doesn't contain any details about the property that failed validation -- if I set up multiple checks, I'd have no idea which one failed or why.

How can I set up a series of checks and retrieve the custom message I've configured? It talks about using req.onValidationError in the Validator readme, but that looks to be front-end validation, I'm not clear how (if possible) to integrate that up with the server-side code.

Upvotes: 0

Views: 3363

Answers (2)

brandonscript
brandonscript

Reputation: 72965

Update, using express-validator:

Per @shawnzhu's suggestion, I implemented express-validator instead; it took a bit of tweaking to get it working with express+connect 3.0, but given it's handling of node-validator errors, it looks like the best way to go (validating headers notwithstanding).

var express = require('express'),
    expressValidator = require('express-validator');

var app = express();

app.use(express.json());
app.use(express.urlencoded());
app.use(expressValidator());

req.checkBody("owner", "<owner> property of type [uuid] is required; " + req.body.owner + " is invalid.").is(uuidRegex);
req.checkBody("photo", "<photo> property of type [uuid] is required; " + req.body.owner + " is invalid.").is(uuidRegex);
req.checkBody("comment", "<comment> property can't be empty").notNull().notEmpty();

req.sanitize("comment").trim();

var errors = req.validationErrors();
if (errors) 
{
    res.json({"result":"failed","errors":errors});
    return;
}

To get it working just with node-validator:

It was the inline message validation that was causing problems:

try {
    check(req.body.owner, "<owner> property of type [uuid] is required").is(/\w{8}(?:-\w{4}){3}-\w{12}?/);
    check(req.body.photo, "<photo> property of type [uuid] is required").is(/\w{8}(?:-\w{4}){3}-\w{12}?/);
    check(req.body.comment, "<comment> property can't be empty").notNull().notEmpty();
} catch (e) {
    res.json({"result":"failed","message":e.message});
}

This does the job, and validates each property based on the criteria.

Upvotes: 0

shawnzhu
shawnzhu

Reputation: 7585

try express-validator which provides errors handling like:

var errors = req.validationErrors();

Upvotes: 2

Related Questions