Search code examples
javascriptnode.jsexpresserror-handling

How do I redirect in Nodejs/Expressjs after user login?


I'm building a online community application in nodejs/expressjs. I'm having some issue with redirecting to the correct page after user has signed in. I have found several articles that relate closely but all of my attempts to fix if from those given articles is not doing the trick.

/*-----------Login and register using email and password------------------- */ 

const register = async (req, res) => {
  const user = await User.create({...req.body });
  try{
    const token = user.createJWT();
    res.status(StatusCodes.CREATED).json({ user: { name: user.name}, token });
    const { name } = user;
    res.redirect(`api/v1/user/${user.name}/dashboard`)

  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message,
    });
  }
};



const login = async (req, res) => {
  const { email, password } = req.body;
  if (!email || !password) {
    throw new BadRequestError("Please provide an email and password");
  }

  try {
    const user = await User.findOne({ email }).select("+password");

    

    if (!user) {
      return res.status(StatusCodes.UNAUTHORIZED).json(" Invalid credentials ");
    }
    const isMatch = await user.matchPassword(password);
    if (!isMatch) {
      throw new UnauthenticatedError("Invalid credentials");
    }
    const token = user.createJWT();
    res.status(StatusCodes.OK).json({ user: {name: user.name}, token});

    const { name } = user;

    res.redirect(`api/v1/user/${name}/dashboard`)

  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message,
    });
  }
};
/*-----------Login and register using email and password------------------- */ 

when use sent and post request on /auth/login or /auth/register it keep throwing error:

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

I'm curious to why this redirect here would not work?


Solution

  • The problem is that json() and redirect() both send the response. And while you can technically achieve what you are looking for by setting the headers and body of response manually and then sending it:

     .get('/test', (req, res) => {
            const jsonData = JSON.stringify({ data: 41 })
            res.statusCode = 200
            res.setHeader('Location', '/otherPage');
            res.setHeader('Content-Type', 'application/json');
            res.setHeader('Content-Length', Buffer.byteLength(jsonData));
            res.write(jsonData);
            res.end()
        })
    

    The redirect will probably make the HTTP reponse return the HTML content or data of the /otherPage. Also, redirect typically have a 3XX status code and making a redirect with a 200 status, which is misleading and definitively not a best practice.

    It is better to send the JSON response with the data and add a redirectPath, that you can then handle in the client.

    res
        .status(200)
        .json({ user: { name: user.name }, token, redirectPath: `api/v1/user/${user.name}/dashboard` })