I am working on expressJS and this is my code in route:
router.route("/")
.post(upload, RecordController.post_record);
and this is the post_record function:
const fs = require("fs");
const readLine = require("readline");
exports.post_record = (req, res) => {
//it's not actually needed but i am doing this just for sake of checking
if (!req.file) {
return res.status(422).json({
message: 'The file is required.'
});
}
//checking if file is empty
if (req.file.size == 0) {
return res.status(400).send("file is empty");
}
try {
// result storing object
const results = {
P: 0,
QRS: 0,
meanFrequency: 0,
minFrequency: {
value: 9999999,
time: 0
},
maxFrequency: {
value: 0,
time: 0
}
};
//for mean frequency calculation
const frequencyCollector = {
sumOfFrequency: 0,
cycleCount: 0
};
//entries of valid wave type object to check if the wave type in our csv are valid data-sets
const expectedWave = {
P: true,
QRS: true,
T: true,
INV: true
};
let time = 0;
let lastTimeStamp = 0;
readLine.createInterface({
input: fs.createReadStream(req.file.path)
}).on("line", line => {
const cols = line.split(",");
const waveType = cols[0];
const startTime = cols[1];
const endTime = cols[2];
const tags = cols.slice(3);
//just to make sure csv has valid data list
if (!(waveType in expectedWave && Number(startTime) >= 0 && Number(endTime) > 0)) {
res.status(500).send("File data entry is not in supported format");
return;
}
else{
if ((waveType === "P" || waveType === "QRS") && tags.includes("premature")) {
results[waveType] ;
}
time = (cols[2] - cols[1]);
time = (cols[1] - lastTimeStamp);
lastTimeStamp = cols[2];
if (waveType === "QRS") {
let frequency = Math.floor((60 / time) * 1000);
//check if frequency is maxValue or minValue
if (frequency > results.maxFrequency.value) {
results.maxFrequency.value = frequency;
results.maxFrequency.time = Number(cols[2]);
}
if (frequency < results.minFrequency.value) {
results.minFrequency.value = frequency;
results.minFrequency.time = Number(cols[2]);
}
frequencyCollector.sumOfFrequency = frequency;
frequencyCollector.cycleCount ;
time = 0;
}
}
}).on("error", (err) => {
return res.status(500).send(`error is: ${err.message}`);
}).on("close", () => {
let heartRate = Math.floor(frequencyCollector.sumOfFrequency / frequencyCollector.cycleCount);
results.meanFrequency = heartRate;
results.maxFrequency.time = Number(req.body.time);
results.minFrequency.time = Number(req.body.time);
res.status(200).json(results);
return;
});
} catch (err) {
console.error(err);
res.status(500).send(`there is an error with message: ${err.message}`);
return;
}
}
and moreOver, this is my main_server file mean where I listen the port:
app.use(bodyParser.json());
//setting the statics
app.use(express.static(path.join(__dirname, "./public/")));
//use record.js file to handle the requests that starts with /things
//settingup the delineation route
app.use("/POST/delineation", recordRoute);
app.get("/", (req, res)=>{
//determine the content-type and automatically set header for us, awesome !!!
res.sendFile(path.join(__dirname, "/index.html"));
});
app.use((req, res, next)=>{
return res.status(404).send("Page not found");
});
//for error handling; error handling middleware
app.use((err, req, res, next)=>{
return res.status(500).send(`Sorry there is error with message saying: ${err.message}`);
})
app.listen(3000, (err)=>{
if(err){
console.log(`there is error - ${err}`);
}
console.log("listening on port 3000");
});
my problem is that whenever i upload a file on the this post route with file that satisfy the error condition of
if (!(waveType in expectedWave && Number(startTime) >= 0 && Number(endTime) > 0)) {
res.status(500).send("File data entry is not in supported format");
return;
}
in the controller code above server give this error:
http_outgoing.js:558 throw new ERR_HTTP_HEADERS_SENT('set'); ^ Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
CodePudding user response:
I think in your readLine
handlers when you return
in its functions, it just return
from those function. try with a return
in behind of readLine.createInterface
CodePudding user response:
The problem is that the stream is still sending the response multiple times from line
event, every time it reads a line.
So, you need to end the stream.
However, it doesn't seem to work like that, because:
Calling rl.close() does not immediately stop other events (including 'line') from being emitted by the InterfaceConstructor instance.
which means the line will emit again, and cause the same error, so you cannot return response from the line
event, but somewhere else.
You need to rewrite the code accordingly.
For example, add the variable to track the error manually, close the stream in line
, and then check for error there, and return error, if any, success if not.
// track error
let error;
// setup reader to close it later
const reader = readLine.createInterface({
//...
if (!(waveType in expectedWave && Number(startTime) >= 0 && Number(endTime) > 0)) {
error = 'File data entry is not in supported format';
// close
reader.close()
return;
}
//...
}).on("close", () => {
if (error) {
res.status(500).send(error);
error = '';
return;
}
//...