2

Here's my code:

app.post('/register', function(req, res){
  var user = new User(req.body);
  if (req.body.password.length <= 5){ res.status(400).send('error: password must be longer'); }
  if (req.body.username.length <= 3){ res.status(400).send('error: username must be longer'); }
  User.findOne({
    username: req.body.username
  }, function(err, userr){
       if(err) {res.status(400).send(err); }
       if (userr){res.status(400).send('error: user already exists'); }
       user.save(function(err, user){
         if (err){ res.status(400).send('couldn\tt save fo sum rezon'); }              
         if (user) { res.send(user); }
       });
    });
});

Here's my error:

home/michael/passport-local-implementation/node_modules/mongoose/node_modules/mpromise/lib/promise.js:108
  if (this.ended && !this.hasRejectListeners()) throw reason;
                                                      ^
Error: Can't set headers after they are sent.

I'm confused about where I'm sending headers more than once? Shouldn't this code stop executing as soon as one of the conditionals are met, or if none are met, then just render the user?

Bonus points if anyone can give me resources on where to read up on the finer points of how express routing works!

Edrosos
  • 70
  • 1
  • 7
h3xc0ntr0l
  • 399
  • 1
  • 3
  • 14
  • Similar to this question (but not an exact duplicate): https://stackoverflow.com/questions/7042340/node-js-error-cant-set-headers-after-they-are-sent – Jason Cust Apr 28 '15 at 15:14

2 Answers2

2

take the following line for example:

if (req.body.password.length <= 5){ res.status(400).send('error: password must be longer'); }

if the condition is met, express will send a response but the function will not return, thus the next line is evaluated et cetera..

You should simply add a return; to make sure the function returns if a response has been sent.

Here's for the bonus points ;) express routing

UPDATE:

You should always use return if you're not using else:

  ...
  var user = new User(req.body);
  if (req.body.password.length <= 5){ res.status(400).send('error: password must be longer'); }
  else if (req.body.username.length <= 3){ res.status(400).send('error: username must be longer'); } 
  else { // include the rest of your function code here... }

This way the rest of your code would only be evaluated in case both if fail..

VF_
  • 2,627
  • 17
  • 17
1

Adding to john's answer

If in your example:

 if (req.body.password.length <= 5){ res.status(400).send('error: password must be longer'); }
  if (req.body.username.length <= 3){ res.status(400).send('error: username must be longer'); }

if the req.body.password.length is less than or equal to 3.

both the conditions are met, and in first if express sends the response, then it agin tries to send the response when the second condition is met. But the are response and thus its headers are already sent( as the error says).


The express send method comprises following tasks:

  1. set headers
  2. set response body
  3. end the response(res.end)

So res.send also ends the response, so you would not be able to send response once it has been sent.

you could rather choose to send response like this

if (req.body.password.length <= 5){ 
    res.status(400).send('error: password must be longer'); 
  } else if (req.body.username.length <= 3){ 
    res.status(400).send('error: username must be longer'); 
  }
Community
  • 1
  • 1
Naeem Shaikh
  • 15,331
  • 6
  • 50
  • 88