Search code examples
node.jsexpress-validator

chaining custom validators in express-validator?


i thought this was pretty straightforward, but i've a feeling that chaining the custom validator with existing ones causes something strange to happen with the req object, which seems to be undefined:

req.checkBody('Game18awayScore', 'must be between 0 and 30').isInt({min:0, max:30}).custom((value,{ req }) => {
        console.log(something);
        if (Math.abs(value - req.body.Game18homeScore) < 2){
          if (value < 30 && req.body.Game18homeScore < 30){
            throw new Error("winning score isn't 2 greater than losing score");
          }
        }
      });
      req.checkBody('homeMan1', 'Please choose a player.').notEmpty().custom((value,{req}) => {
        if (value != 0){
          if (value == req.body.homeMan2 || value == req.body.homeMan3 || value == req.body.awayMan1 || value == req.body.awayMan2 || value == req.body.awayMan3){
            throw new Error("can't use the same player more than once")
          }
        }

      });

but i just keep getting: TypeError: Cannot destructure propertyreqof 'undefined' or 'null'.

The first custom is checking that there's a difference of at least two between the two values, unless one of the values is 30.

The second custom is checking that one value isn't being used in the other 5 options.

I should add, this block of code is in a validator Function:

function validateScorecard (req,res,next){ [all my validations for the form including the ones above] }

which is then included in the route: app.post('/scorecard-beta',validateScorecard, fixture_controller.full_fixture_post);

any ideas?


Solution

  • Using .custom() to specify an inline validator like this doesn't work when you are using the legacy API (eg req.checkBody(...).custom()).

    The legacy API has had support for custom validators in a quite different way for some years:
    You specify them as options in your express-validator middleware, and they are made available when you use req.checkBody(...).
    These can then receive additional arguments other than the field's value.

    Example:

    app.use(expressValidator({
        customValidators: {
            isMagicNumber(value, additionalNumbers) {
                return value === 42 || additionalNumbers.includes(value);
            }
        }
    }));
    
    app.post('/captcha', (req, res, next) => {
        // world's safest captcha implementation
        req.checkBody('answer').isMagicNumber();
        req.checkBody('answer').isMagicNumber([req.user.age]);
    });
    

    The .custom() call kinda works because the method is there, but internally in the legacy API, express-validator doesn't know how you defined it.

    Your solutions?

    • Keep using it like that, but refrain from using additional args, as that would come against what is documented for .custom().
    • stop using the legacy API, as it is deprecated and will be removed eventually.