Home > Back-end >  Code still executing after returning res.send
Code still executing after returning res.send

Time:06-30

I have a function that will return a response res.send() but after that function is called, the following line of code is till executed.

const db = require('../models');

exports.findAll = (req, res) => {
    checkAuthorization(req, res, 'Customer');

    db.User.findAll({ include: ['created', 'restaurant'] })
        .then((data) => {
            res.send({
                error: false,
                data: data,
                message: ['Retrieved successfully.'],
            });
        })
        .catch((err) => {
            console.log(err);
            res.status(500).send({
                error: true,
                data: [],
                message: err.errors.map((e) => e.message),
            });
        });
};

Here is the checkAuthorization function

const checkAuthorization = (req, res, user_type) => {
    // Check if user_type param is null
    if (user_type == null) return res.status(500).send('`user_type` parameter is required');

    // Check if user_type param has valid value
    const validuser_type = user_type === 'Customer' || user_type === 'Resto_Admin' || user_type === 'Admin';

    // Validate user_type parameter
    if (!validuser_type) return res.status(500).send('The value for `user_type` parameter is invalid');

    // Check if user is not authorized
    if (!(req.user != null && req.user.user_type === user_type))
        return res.status(401).send('Oops! You are unauthorized to view your request');
};

Here is the error I get.

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

CodePudding user response:

"Returning from a function" and "returning a response to the user from a web server" are two very different things. The checkAuthorization function is sending a response, but then doesn't indicate to the calling function that it did that. So the calling function also tries to send a response.

Don't "return" the call to res.status from checkAuthorization. If it needs to send a response, it can do so but should also return from the function some indication that it did this. Something as simple as a boolean value can work. For example:

const checkAuthorization = (req, res, user_type) => {
  // Check if user_type param is null
  if (user_type == null) {
    res.status(500).send('`user_type` parameter is required');
    return false;
  }
  // and so on for the other responses...

  // then, if no condition produced an HTTP response...
  return true;
}

And then when invoking that function:

exports.findAll = (req, res) => {
  if (!checkAuthorization(req, res, 'Customer')) {
    // the function internally sent a response, stop processing
    return;
  }

  db.User.findAll({ include: ['created', 'restaurant'] })
  //...
};

As an aside... This overall logic structure can get confusing fast. What you probably want to do is move your checkAuthorization logic into its own middleware that would be invoked on every request, before the request even reaches the findAll logic in this case.

In the middleware pipeline you can use res to send a response to the user and then end processing, or invoke next to continue processing.

  • Related