Home > Mobile >  Getting code: 'ERR_HTTP_HEADERS_SENT' when calling login API
Getting code: 'ERR_HTTP_HEADERS_SENT' when calling login API

Time:07-22

The Error I am facing is that, I am able to fetch data smoothly from mongo db until and unless I submit the login form. On submitting the login form, I get an error

     Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:372:5)
at ServerResponse.setHeader (node:_http_outgoing:576:11)
at ServerResponse.header (E:\Blog-Website\api\node_modules\express\lib\response.js:794:10)
at ServerResponse.send (E:\Blog-Website\api\node_modules\express\lib\response.js:174:12)
at ServerResponse.json (E:\Blog-Website\api\node_modules\express\lib\response.js:278:15)
at E:\Blog-Website\api\routes\auth.js:37:23
at processTicksAndRejections (node:internal/process/task_queues:96:5) { 
code: 'ERR_HTTP_HEADERS_SENT'

I have searched a lot and was basically following a tutorial for creating my first MERN project. But am not able to figure out which header is getting repeatedly.

Below is my backend auth.js code

   const router = require("express").Router();
   const User = require("../models/User");
   const bcrypt = require('bcrypt');

  //REGISTER
  router.post("/register", async (req, res) => {
  try {
    const salt = await bcrypt.genSalt(10);
    const hashedPass = await bcrypt.hash(req.body.password, salt);
    const newUser = new User({
    username: req.body.username,
    email: req.body.email,
    password: hashedPass,
});

   const user = await newUser.save();
   console.log(user)
    res.status(200).json(user);
   } catch (err) {
  res.status(500).json(err);
 }
});

 //LOGIN

 router.post("/login", async (req, res) => {
 try {
const user = await User.findOne({ username: req.body.username });
!user && res.status(400).json("Wrong credentials!");

const validated = await bcrypt.compare(req.body.password, user.password);
!validated && res.status(400).json("Wrong credentials!");

   const { password, ...others } = user._doc;
   res.status(200).json(others);
    } catch (err) {
   res.status(500).json(err);
  }
});


module.exports = router

and Below is my front-end code login.jsx

      import { Link } from "react-router-dom";
      import "./login.css"
      import { useContext, useRef } from "react";
      import axios from "axios";
      import { Context } from "../../../context/Context";

      export default function Login() {

     const userRef = useRef();
      const passwordRef = useRef();
      const { user, dispatch, isFetching } = useContext(Context);


       const handleSubmit = async (e) => {
      e.preventDefault();
       dispatch({ type: "LOGIN_START" });
      try {
        const res = await axios.post("/auth/login", {
        username: userRef.current.value,
        password: passwordRef.current.value,
        });
          dispatch({ type: "LOGIN_SUCCESS", payload: res.data });
        } catch (err) {
       dispatch({ type: "LOGIN_FAILURE" });
      }
    };

     console.log(user)

       return (
     <div className="login">
      <span className="loginTitle">Login</span>
     <form className="loginForm" onSubmit={handleSubmit}>
    <label>Username</label>
    <input className="loginInput" type="text" placeholder="Enter your username..." ref= 
    {userRef} />
    <label>Password</label>
    <input className="loginInput" type="password" placeholder="Enter your password..." ref= 
  {passwordRef} />
    <button className="loginButton" type="submit">Login</button>
      </form>
       <button className="loginRegisterButton">
        <Link className="link" to="/register">Register</Link>
      </button>
     </div>
     );
  }

  

I've been googling it for 4 hours but I still don't get where my mistake come from!!

Any help is highly appreciated

CodePudding user response:

I think the bug lies within these lines:

const user = await User.findOne({ username: req.body.username });
!user && res.status(400).json("Wrong credentials!");

const validated = await bcrypt.compare(req.body.password, user.password);
!validated && res.status(400).json("Wrong credentials!");

Calling res.status(... when the user is not found does not interrupt execution - it will proceed forward to res.status(200).json(others), which will send another set of headers to the client.

To fix this, you can simply add a return statement like so:

const user = await User.findOne({ username: req.body.username });
if (!user)
  return res.status(400).json("Wrong credentials!");

const validated = await bcrypt.compare(req.body.password, user.password);
if (!validated)
  return res.status(400).json("Wrong credentials!");

That way, execution halts on an error and res.status(... is called exactly once.

  • Related