Home > database >  Can't set headers after they are sent to the client [ERR_HTTP_HEADERS_SENT]
Can't set headers after they are sent to the client [ERR_HTTP_HEADERS_SENT]

Time:02-25

I understood why it was an error, I tried the suggestions like return or do function aysnc, but I could not solve it.

I have documents as long as find.lenght and 100 sub-documents. That's why I am use two loop. When first iteration is complete and second matching value is found, server is crashed. Without server it works.

I have documents called 0,1,2 and there are 100 crypto coins records from 0 to 100 in them. I added an image. For example, USDT is at [0,3], [1,43], [2,13] and I want to send all of three.

app.post('/', (req, res) => {
  print(req, res)
})

function print(req, res) {
  MongoClient.connect(url, function (err, db) {
    if (err) throw err;
    var dbo = db.db("cryptoDb");
    dbo.collection("coinTable").find({}).toArray(function (err, find) {
      if (err) throw err;

      for (i = 0; i < find.length; i  ) {
        let found = false;
        for (j = 0; j < 100; j  ) {
          //console.log(i   " "   j)
          let id = Capitalize(req.body.coinName);
          if (find[i].result[j].name == id || find[i].result[j].symbol == id.toUpperCase()) {
            // console.log(find[i].result[j]);
            res.send(find[i].result[j]);
            found = true;
          }
        }
        if (!found) {
          console.log("Not found")
        }
      }
      db.close();
    });
  });

  function Capitalize(s) {
    return s[0].toUpperCase()   s.slice(1).toLowerCase();
  }
}

mongotree

mongotree2 Thank you so much !

CodePudding user response:

This error comes from attempting to send more than one response to the same http request.

You have res.send(find[i].result[j]); inside a for loop and you do not stop the inner loop after sending a response.

Thus, this code is capable of attempting to send multiple responses to the same request which you cannot do.

It's unclear from the code exactly what the desired solution is. If you only want to send the first response, then you can close the db and return after you send a response which will terminate both for loops.

If you intend to send multiple pieces of data, then accumulate the data you want to send in an array and send all the data once after all the loops are done.


If you're trying to send an array of all matching results, you can do this:

app.post('/', (req, res) => {
    print(req, res)
})

function print(req, res) {
    MongoClient.connect(url, function(err, db) {
        if (err) {
            console.log(err);
            res.sendStatus(500);
            return;
        }
        var dbo = db.db("cryptoDb");
        dbo.collection("coinTable").find({}).toArray(function(err, find) {
            if (err) {
                console.log(err);
                res.sendStatus(500);
                db.close();
                return;
            }

            const id = Capitalize(req.body.coinName);
            const idUpper = id.toUpperCase();
            const results = [];
            for (let findItem of find) {
                for (let j = 0; j < 100; j  ) {
                    if (findItem.result[j].name == id || findItem.result[j].symbol == idUpper) {
                        results.push(findItem.result[j]);
                    }
                }
            }
            res.send(results);
            if (!results.length) {
                console.log("No results");
            }
            db.close();
        });
    });

    function Capitalize(s) {
        return s[0].toUpperCase()   s.slice(1).toLowerCase();
    }
}

Other Notes:

  1. I changed the if (err) { ... } handling on your database call to actually send an error response. All paths through your request handler need to send a response or cause a response to be sent.

  2. The hard coded loop from 0 to 99 is a bit odd as you don't check if the .result array actually has that many entries in it. That could result in a run-time error if the data isn't exactly how you are expecting it.

  3. You don't have any validation of the req.body data you are expecting. All data arriving from the user should be validated before assuming it is what you are expecting.

CodePudding user response:

You have res.send inside of your for loop, im assuming you want it to quit once its done, so add break to your loop.

var senddata = [];
for (j = 0; j < 100; j  ) { // <-- For loop, it will send multiple times
  // console.log(i   " "   j)
  let id = Capitalize(req.body.coinName);
  if (find[i].result[j].name == id || find[i].result[j].symbol == id.toUpperCase()) {
    // console.log(find[i].result[j]);
    senddata[senddata.length] = find[i].result[j]); // Add to array
    found = true;
  }
  if (!found) {
    console.log("Not found")
  }
}
res.send(JSON.stringify({senddata})); // Send unparsed data
  • Related