Reputation: 2955
I recently installed express-validator into my Express JS project, but when sending invalid fields to my api, I get this warning:
UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
followed by:
DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I'm not sure why I'm getting this since many guides show the use of the validation logic inside of the post
as an Array, yet if I remove this then I don't get any warnings, what am I missing?
src/routes/api.js
const router = require('express').Router();
const { check, validationResult } = require('express-validator');
const emulation = require('../utils/emulator');
router.post('/my-endpoint', [
check('url').trim().not().isEmpty().withMessage('URL must be provided'),
check('userAgent').trim().not().isEmpty().withMessage('userAgent must be provided')
], async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(422).send({
success: false,
msg: "There are validation errors, please fix them and try again",
errors: errors.array()
});
}
const emulate = await emulation.runEmulation(req.body.url);
res.status(200).send({
success: true
});
} catch (err) {
res.status(500).send({
success: false,
msg: err.message != null ? err.message : err
});
}
})
module.exports = router
The main entry where this route is called looks much like the following:
const fs = require('fs');
const cors = require('cors');
const http = require('http');
const helmet = require('helmet');
const express = require('express');
const basicAuth = require('express-basic-auth');
const rateLimit = require('express-rate-limit');
const { config } = require('./src/utils/config');
const limiter = rateLimit({
windowMs: 1 * 60 * 1000,
max: 60,
message: {
success: false,
msg: 'Too many requests, slow down'
}
});
const app = express();
const api = require('./src/routes/api');
app.use(helmet({
frameguard: false
}));
app.use(cors());
app.use(express.json());
app.use(limiter);
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
app.use(basicAuth({
users: { 'user': config.apiKey },
unauthorizedResponse: getUnauthorizedResponse
}))
function getUnauthorizedResponse(req) {
return { success: false, msg: 'Credentials are incorrect or aren\'t provided' }
}
app.use('/api', api);
app.use((req, res, next) => {
const error = new Error('Not Found')
error.status = 404
next(error)
})
app.use((error, req, res, next) => {
res.status(error.status || 500).send({ error: {
status: error.status || 500,
message: error.message || 'Internal Server Error',
},
})
})
process.on('uncaughtException', function (err) {
console.error(err)
console.log('API (node) NOT Exiting...')
})
http.createServer(app).listen(config.port, config.ip, () => {
console.log(`API running on: http://${config.ip}:${config.port}`)
})
Any explanation for my error would be appreciated
Upvotes: 0
Views: 1476
Reputation: 59
You can send one response at the time, but your code send more than one. if condition was false means no worry, but true means response send two times. You write the code like this
if (!errors.isEmpty()) {
res.status(422).send({
success: false,
msg: "There are validation errors, please fix them and try again",
errors: errors.array()
});
}else{
const emulate = await emulation.runEmulation(req.body.url);
res.status(200).send({
success: true
});
}
Or
if (!errors.isEmpty()) {
res.status(422).send({
success: false,
msg: "There are validation errors, please fix them and try again",
errors: errors.array()
});
return
}
const emulate = await emulation.runEmulation(req.body.url);
res.status(200).send({
success: true
});
Upvotes: 1