I created a middleware that validates the request input before calling the controller logic.
Let's say I have a "get user by id" - route
const usersController = require('../controllers/users.js');
const usersControllerPolicy = require('../policies/users.js');
router.get('/:userId', usersControllerPolicy.getUserById, usersController.getUserById);
// other routes
Before executing the controller I use the policy to validate the params and the body. My policy module for users is
const joi = require('joi');
const schemaValidation = require('../middleware/schemaValidation.js');
module.exports = {
getUserById: (req, res, next) => {
schemaValidation({
userId: joi.string().guid().required()
}, req, res, next);
}
// other routes
}
The userId
is a route parameter, not a variable within the body. The
schemaValidation
middleware validates the given schema and calls next()
or sends a 400
response.
const joi = require('joi');
const requestResponder = require('../helpers/requestResponder.js');
module.exports = (schema, req, res, next) => {
const { error } = joi.validate(req, schema);
if (error)
return requestResponder.sendBadRequestError(res);
next();
}
When I call this route with /users/137eaa6f-75c2-46f0-ba7c-c196fbfa367f
I get this error
message: '"userId" is required'
but the validation should be fine. I checked the validation joi.validate(req, schema)
by logging req.params
and the userId is available. What am I missing?
Edit:
I know I could validate req.params
but what if I want to update a user? I would have to validate the params (userId) and the body (name, age, ...)
I created a middleware that validates the request input before calling the controller logic.
Let's say I have a "get user by id" - route
const usersController = require('../controllers/users.js');
const usersControllerPolicy = require('../policies/users.js');
router.get('/:userId', usersControllerPolicy.getUserById, usersController.getUserById);
// other routes
Before executing the controller I use the policy to validate the params and the body. My policy module for users is
const joi = require('joi');
const schemaValidation = require('../middleware/schemaValidation.js');
module.exports = {
getUserById: (req, res, next) => {
schemaValidation({
userId: joi.string().guid().required()
}, req, res, next);
}
// other routes
}
The userId
is a route parameter, not a variable within the body. The
schemaValidation
middleware validates the given schema and calls next()
or sends a 400
response.
const joi = require('joi');
const requestResponder = require('../helpers/requestResponder.js');
module.exports = (schema, req, res, next) => {
const { error } = joi.validate(req, schema);
if (error)
return requestResponder.sendBadRequestError(res);
next();
}
When I call this route with /users/137eaa6f-75c2-46f0-ba7c-c196fbfa367f
I get this error
message: '"userId" is required'
but the validation should be fine. I checked the validation joi.validate(req, schema)
by logging req.params
and the userId is available. What am I missing?
Edit:
I know I could validate req.params
but what if I want to update a user? I would have to validate the params (userId) and the body (name, age, ...)
-
If
userID
is available inreq.params
then should you validatereq.params
? e.g.joi.validate(req.params, schema)
– Igor Commented Mar 20, 2019 at 15:41 - @Igor yes but I need to validate the params and the body. I pass in the userId as a parameter but there might be variables to validate in the body too. – user9945420 Commented Mar 20, 2019 at 15:57
1 Answer
Reset to default 6Your joi validation schema should reflect req
object structure, that should work:
const joi = require('joi');
const schemaValidation = require('../middleware/schemaValidation.js');
module.exports = {
getUserById: (req, res, next) => {
schemaValidation(joi.object({
params: joi.object({
userId: joi.string().guid().required()
}).unknown(true)
}).unknown(true), req, res, next);
}
// other routes
}
When you need to validate both body and params:
const joi = require('joi');
const schemaValidation = require('../middleware/schemaValidation.js');
const paramsValidation = joi.object({
userId: joi.string().guid().required()
}).unknown(true);
const bodyValidation = joi.object({
name: joi.string().required()
}).unknown(true);
module.exports = {
getUserById: (req, res, next) => {
schemaValidation(joi.object({
params: paramsValidation,
body: bodyValidation
}).unknown(true), req, res, next);
}
// other routes
}
But i would rather prefer to validate them separately with 3 joi schemas (body, params, query) e.g. how it done here https://www.npmjs./package/express-joi-validation#validation-ordering