Pritam Bohra
Pritam Bohra

Reputation: 4319

ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client at ServerResponse

I am trying to create a simple REST API with NodeJS and Express without any database. I have stored all of my data in JSON files. The data is in the form of an array of objects.

I have paths like fund-name/:portId

so I am doing this:

const fundName = require('./json/fund-name.json');

app.get('/fund-details:portId', (req, res) => {

    const portId = req.params.portId;
    fundDetails.forEach(fund => {
        if (fund.portId === portId) {
            return res.json(fund);
        }

        return res.json([]);
    });
});

when I hit the url http:localhost:3000/fund-details/1234, I get the following error:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:470:11) at ServerResponse.header (/home/username/Desktop/data-server/node_modules/express/l ib/response.js:767:10)

It works fine when I don't pass any path param to get all the funds. Where am I going wrong??

Upvotes: 6

Views: 19694

Answers (2)

Rajan Lagah
Rajan Lagah

Reputation: 2528

This error is because you are using res.send() multiple time in single api call.
Correct way

if(a){
 res.send()
}else{
 res.send()
}

Wrong way

if(a){
 res.send()
 res.send()
}else{
 res.send()
}

In your code.

app.get('/fund-details:portId', (req, res) => {
const portId = req.params.portId;
fundDetails.forEach(fund => {
    if (fund.portId === portId) {
        return res.json(fund); // many or single times here
    }
    return res.json([]); // and here when fund !==portId here 
});
});

You can try

app.get('/fund-details:portId', (req, res) => {

const portId = req.params.portId;
var flag 
var data = []
fundDetails.forEach(fund => {

 if (fund.portId === portId) {
       flag=true
       data.push(fund)
    }
});
if(flag){
    res.send(data);
}else{
    res.send()
}
});

Upvotes: 17

Danyal Imran
Danyal Imran

Reputation: 2605

The method res.json(fund) is called per each item in fundDetails and then a further res.json([]) method is called. This leads to your response being send back multiple times (which it shouldn't happen, only 1 response per a single api call should be used).

I suggest that you use an array and push back objects with the matching port id and then send the array back to the user when the operation is completed. To be honest, you don't even need the flag variable to check if funds exists or not since if they don't, you empty data array is sent back.

var data = [];
fundDetails.forEach(fund => {
  if (fund.portId === portId)
    data.push(fund);
});

res.json(data);

Upvotes: 2

Related Questions