Reputation:
I'm trying to do something like this,
// /api/auth
const validateFields = ({ name, email }, res) => {
if (!name.trim()) return res.status(422).json({ error: 'name' })
if (!email.trim()) return res.status(422).json({ error: 'email' })
}
router.post('/', async (req, res) => {
const { name = '', email = '' } = req.body
validateFields({ name, email }, res)
return res.end()
})
If someone passes an invalid name or email, let's say an empty string, the frontend received the expected error, but the backend (ExpressJS) throws an error,
Error: Can't set headers after they are sent
I'm kind of forced to do the following,
const validateFields = ({ name, email }, res) => {
if (!name.trim()) return res.status(422).json({ error: 'name' })
if (!email.trim()) return res.status(422).json({ error: 'email' })
return true
}
router.post('/', async (req, res) => {
const { name = '', email = '' } = req.body
const validFields = validateFields({ name, email }, res)
if (validFields !== true) return
return res.end()
})
Is this my only option here?
Upvotes: 1
Views: 1643
Reputation: 5051
for validate req.body
or req.params
use 'Joi', joi is the most powerful schema description language and data validator for JavaScript, check this article
Upvotes: 0
Reputation: 707986
That isn't the only way to code it, but you will generally have to check to see if there was an error and, if not, then send your normal response.
I personally don't like functions that sometimes send a response and sometimes don't as that confuses the logic flow. I find it better to either make a function that sends all possible responses or make it a function that just returns status and the caller then sends the response. Or, use the middleware design where if it sends a response, then processing doesn't continue any further (because next()
is not called).
In this particular case, you could just return the error status and let the caller send the final response. Then it's always consistent. The response is always sent by the caller and validateFields()
just returns a result:
const validateFields = ({ name, email }) => {
if (!name.trim()) return { status: 422, error: 'name' };
if (!email.trim()) return { status: 422, error: 'email' };
return { status: 200, ok: true };
}
router.post('/', async (req, res) => {
const { name = '', email = '' } = req.body;
const result = validateFields({ name, email });
res.status(result.status).json(result);
});
The middleware design could work like this:
const validateFields = (req, res, next) => {
const { name = '', email = '' } = req.body;
if (!name.trim()) return res.status(422).json({ error: 'name' });
if (!email.trim()) return res.status(422).json({ error: 'email' });
next();
}
router.post('/', validateFields, async (req, res) => {
res.send("ok");
});
Upvotes: 2