Search code examples
javascriptnode.jsmongodbexpressmiddleware

I get an UnhandledPromiseRejection with Express middleware


I'm trying to check if a user is logged in before trying to access the addContact endpoint.

var isLoggedIn = (req, res, next) => {
   if(req.session.user)
       next();

   //unauthorized
   res.status(401).send('Please log in.');
};

The post route addContact looks like this and I'm using the isLoggedIn middleware to check if a user signed in before adding.

app.post('/addContact', isLoggedIn, (req, res) => {

   //if Mongo database is not started
   if(mongoose.connection.readyState !== 1) {
       res.send(`We're sorry. We are having trouble connecting. Try again later`);
       return;
   }

   var contact = new Contact({
       _userId: req.session.user.id,
       name: req.body.name,
       phone_number: req.body.phone_number,
       email: req.body.email
   });

   console.log('adding contact from session', req.session.user);

   contact.save().then((c) => {
       res.send(`${contact.name} was added succesfully.`);
   }).catch((e) => {
       res.send(e);
   });

});

'Adding contact from session:' is being logged to the console with the right session id req.session.user. But once it tries to save() the new contact, I am getting the following error

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Cannot set headers after they are sent to the client

And the response that is being sent says 'Please log in' which is specified in the middleware isLoggedIn.

Can somebody tell me why is this happening? I'm trying not to duplicate questions but I can't find a solution. Thanks


Solution

  • You need to return after your call to next:

    var isLoggedIn = (req, res, next) => {
       if(req.session.user) {
           next();
           return;
        }
    
       //unauthorized
       res.status(401).send('Please log in.');
    };
    

    And actually better yet:

    var isLoggedIn = (req, res, next) => {
       if (!req.session.user) {
           const err = new Error('Please login')
           err.status = 401
           throw err
        }
    
       next()
    };
    

    Then have actual error handler middleware:

    /**
     * Show useful information to client in development.
     */
    exports.development = (err, req, res, next) => {
      err.stack = err.stack || ''
      const status = err.status || 500
    
      res.status(status).json({
        status,
        error
      })
    }
    
    /**
     * Do not show errors in production.
     */
    exports.production = (err, req, res, next) => {
      if (err.stack) {
        delete err.stack
      }
    
      err.message = err.messsage || 'oops'
      err.status = err.status || 500
    
      res.status(err.status).json({
        status: err.status,
        error: {
          message: err.message
        }
      })
    }