i am trying to implement a Rest API but Joi validation conflicts if i create separate routers for different http methods for the same route, like below.
Router 1:
Path: ‘/’,
Method: Get,
Joi Schema: ‘Schema 1’,
Router 2:
Path: ‘/’,
Method: Post,
Joi Schema: ‘Schema 2’,
Router 3:
Path: ‘/’,
Method: Patch,
Joi Schema: ‘Schema 3’,
Main Router:
Path: ‘path-name’
Use: Router 1,
Use: Router 2,
Use: Router 3,
The problem occurs in the Router 3’s joi validation.
Here is the corresponding files.
Get.mjs – Router 1
import express from 'express';
import { necessarySchemas } from '../../schemas.mjs';
import { Validator } from '../../validator.mjs';
const router = express.Router();
router.use(Validator.validateAuthorizationBearerJwt(authorizationSchema));
router.get('/', async (req, res) => {
// code here
});
router.get('/:id', Validator.validate(schema1, { params: true }), async (req, res) => {
// code here
});
export default router;
Post.mjs – Router 2
import express from 'express';
import { necessarySchemas } from '../../schemas.mjs';
import { Validator } from '../../validator.mjs';
const router = express.Router();
router.use(Validator.validateAuthorizationBearerJwt(authorizationSchema));
router.use(Validator.validate(schema2))
router.post('/', async (req, res) => {
// code here
});
export default router;
Patch.mjs – Router 3
import express from 'express';
import { necessarySchemas } from '../../schemas.mjs';
import { Validator } from '../../validator.mjs';
const router = express.Router();
router.use(Validator.validateAuthorizationBearerJwt(authorizationSchema));
router.use(Validator.validate(schema3));
router.patch('/:id', Validator.validate(schema4, { params: true }), async (req, res) => {
// code here
});
export default router;
Router.mjs – Main Router
import express from 'express';
import get from './get.mjs';
import post from './post.mjs';
import patch from './patch.mjs';
const router = express.Router();
router.use('/', get);
router.use('/', post);
router.use('/', patch);
export default router;
Here are the schemas
export const schema1 = Joi.object({
id: Joi.number().min(0).required(),
});
export const schema2 = Joi.object({
shareCode: Joi.string().length(6),
});
export const schema3 = Joi.object({
name: Joi.string().min(6).max(50).required(),
});
export const schema4 = Joi.object({
id: Joi.number().min(0).required(),
});
Validator
validate(schema, source = { body: true, params: false, query: false }) {
return (req, res, next) => {
var result = null;
if (source.body) {
result = schema.validate(req.body);
} else if (source.params) {
result = schema.validate(req.params);
} else if (source.query) {
result = schema.validate(req.query);
}
if (result.error) {
return res.status(400).json({
message: result.error.details[0].message,
});
}
next();
};
}
What happens is that if i send a patch request and add the field ‘name’ in the body i get this response
{
"message": ""name" is not allowed"
}
and if i delete that field i get
{
"message": ""name" is required"
}
Removing post router from the Main Router gets rid of the problem.
Also if change the .use to .post and .patch like below is also a fix
router.use('/', get);
router.post('/', post);
router.patch('/', patch);
My question is why this problem occurs in the first place? Express can handle http requests by the http method that is used so joi validation shouldn’t conflict right? but it does for some reason.
Since i can not remove post router can you explain why using it the way on top works?
Also are there any other solutions to this except for using different path names?
Thanks in advance!