airsoftFreak airsoftFreak - 2 months ago 14
Node.js Question

Error: Can't set headers after they are sent , happen only after refreshing a page

Every time i refresh a html page at route 'localhost:8080/' or login a user I will get this Error: Can't set headers after they are sent. As far as I know this problem happens due to callbacks that are accidentally called twice. The app doesn't crash or anything, its just keep logging the same error on the console.

Here's the code.

var User = require('../models/user');
var Story = require('../models/story');
var jwt = require('jsonwebtoken');
var config = require('../../config');


var superSecret = config.secret;


module.exports = function(app, express) {

// creating our first router
var apiRouter = express.Router();

// signup a user

apiRouter.post('/signup', function(req, res) {

var user = new User({
name: req.body.name,
username: req.body.username,
password: req.body.password
});

user.save(function(err) {
if(err) res.send(err);
res.json({ message: 'User has been created!' });
});
});

apiRouter.get('/users', function(req, res) {

User.find({}, function(err, users) {

if(err) res.send(err);

res.json(users);

});

});



// user login

apiRouter.post('/login', function(req, res) {

User.findOne({
username: req.body.username
}).select('name username password').exec(function(err, user) {

if(err) throw err;

if(!user) {
res.json({ message: "Wrong User" });
} else if(user) {

var validPassword = user.comparePassword(req.body.password);

if(!validPassword) {
res.json({ message: "Invalid Password" });

} else {

var token = jwt.sign({
id: user._id,
name: user.name,
username: user.username
}, superSecret, {
expiresInMinute: 1440
});

// return all the sucess
res.json({
success: true,
message: "Successfully login and token created!" + token.name,
token: token

});
};

}

});

});


// write a middleware for login
// A middleware for login user only, once a user has logged in , he can enter other links below
apiRouter.use(function(req, res, next) {

// do logging
console.log("Somebody just came to our app!");

var token = req.body.token || req.param('token') || req.headers['x-access-token'];

// check if token exist
if(token) {

jwt.verify(token, superSecret, function(err, decoded) {
if(err) {
res.status(403).send({ success: false, message: 'Failed to authenticate user' });
} else {

// if everything is good save request for use in other routes
req.decoded = decoded;

next();
}
});

} else {
res.status(403).send({ success: false, message: 'No token provided' });
}
});


apiRouter.route('/')

.post(function(req, res) {

var story = new Story({
user: req.decoded.id,
content: req.body.content
});

story.save(function(err, stor) {
if(err) res.send(err)
console.log(stor);
res.json(stor);
});

})


.get(function(req, res) {

Story.find({ user: req.decoded.id }, function(err, story) {
if(err) res.send(err);

res.json(story);
});


});




apiRouter.get('/me', function(req, res) {

res.send(req.decoded.name);

});

apiRouter.route('/:user_id')


.get(function(req, res) {

User.findById(req.params.user_id, function(err, user) {
if(err) res.send(err);

res.json(user);

});


})

.put(function(req, res) {

User.findById(req.params.user_id, function(err, user) {

if(err) res.send(err);

if(req.body.name) {
user.name = req.body.name;
}

if(req.body.username) {
user.username = req.body.username;

}

if(req.body.password) {
user.password = req.body.password;
}

user.save(function(err) {
if(err) res.send(err);

res.json({ message: "User updated" });

});


});

});

return apiRouter;

}

Answer

You are sending a response twice when an error occurs:

if (err) res.send(err);
res.json(foo);

Replace that with:

if (err) { res.send(err); return; }
res.json(foo);