Reputation: 19
I am creating an api that will call a python script using python-shell in nodejs.However when I am running the api,the api returns the error of "Cannot set headers after they have been sent to the client".Below is the code for the api.
app.post(
"/uploadFacial",
multer({
storage: storage
}).single('upload'), function(req, res) {
console.log(req.file.filename);
var userid = req.body.upload[1];
console.log("User id: "+userid);
var success = true;
var message = '';
var subStringUserId = userid.substring(1,userid.length-1);
var dir = "./users/"+subStringUserId;
//res.setHeader("Content-Type", "application/json");
console.log(dir);
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
success = false;
message = 'Cannot detect the person.Please add name in the textbox provided below to save the person.';
res.status(200).json({message: message,success:success});
res.end();
}else {
console.log("in else");
var options={
mode:'text',
encoding:'utf-8',
pythonOptions:['-u'],
scriptPath:'./',
pythonPath:'',
args:[subStringUserId,req.file.filename]
}
var facialScript = new PythonShell('face_detect.py',options)
facialScript.on('message',(response)=>{
console.log(response);
res.status(200).send(response);
//res.end();
})
facialScript.on('error',(err)=>{
console.log(err);
})
}
});
Below is the python code if needed
from deepface import DeepFace
from os.path import join, dirname, realpath
import os, sys
import json
PARENT_DIR = join(dirname(realpath(__file__)), './users/')
TEST_DIR = join(dirname(realpath(__file__)), './uploads/')
print(json.dumps({'success':False,'message':'Cannot detect at moment.Please try later'})) #this is only for debugging
user_id = sys.argv[1]
img_name = sys.argv[2]
db = os.path.join(PARENT_DIR, user_id)
img = os.path.join(TEST_DIR, img_name)
try:
df=DeepFace.find(img_path=img,db_path=db, model_name = "Facenet")
if(df.size==0):
print(json.dumps({'message': 'Cannot detect the person.Please add name in the textbox provided below to save the person.','success':False}))
else:
print(json.dumps({'success':True,'message':os.path.splitext(os.path.basename(df['identity'][0]))[0]}))
except Exception as e:
#logger.error('Failed to upload to ftp: '+ str(e))
a = 1
Here is the error
throw new ERR_HTTP_HEADERS_SENT('set');
^
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 (/Users/priyamvora/Node/Drishti/ImageUploadTest/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/Users/priyamvora/Node/Drishti/ImageUploadTest/node_modules/express/lib/response.js:170:12)
at PythonShell.facialScript.on (/Users/priyamvora/Node/Drishti/ImageUploadTest/multipart.js:129:27)
at PythonShell.emit (events.js:182:13)
at /Users/priyamvora/Node/Drishti/ImageUploadTest/node_modules/python-shell/index.js:324:22
at Array.forEach (<anonymous>)
at PythonShell.receiveInternal (/Users/priyamvora/Node/Drishti/ImageUploadTest/node_modules/python-shell/index.js:322:15)
at PythonShell.receive (/Users/priyamvora/Node/Drishti/ImageUploadTest/node_modules/python-shell/index.js:296:21)
at Socket.emit (events.js:182:13)
Kindly help at the earliest.
Upvotes: 0
Views: 320
Reputation: 1773
This is because the "message" event listener is fired more than once that's why even res.status(200).send(response);
line is executing more than once which is causing this problem. Try to accumulate the result of event listener in one variable and that send the response(only once).
Something like this:
let result="";
facialScript.on('message',(response)=>{
result=result+response;//assuming that response is string you can change this as per your convenience .
})
facialScript.on("end",()=>{
res.send(result);
})
Also you have to remove res.status(200).json({message: message,success:success});
inside if condition for identifying if directory exists or not!!
Upvotes: 1
Reputation: 169
If this if loop get executed a response will be send
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
success = false;
message = 'Cannot detect the person.Please add name in the textbox provided below to save the person.';
res.status(200).json({message: message,success:success});
res.end();
A response is trying to send in below code too
var facialScript = new PythonShell('face_detect.py',options)
facialScript.on('message',(response)=>{
console.log(response);
res.status(200).send(response);
//res.end();
})
Which is not included in the else loop.
Upvotes: 2