ERR_HTTP_HEADERS_SENT 将标准输出用于 node.js / express 时出错
ERR_HTTP_HEADERS_SENT error when using stdout for node.js / express
运行 进入我的节点应用程序中有据可查的“错误 [ERR_HTTP_HEADERS_SENT]:将它们发送到客户端后无法设置 headers”。我已经查看了专门针对此问题的现有页面并尝试了他们的补救措施 - 主要是确保“return”所有其他响应;但是错误仍然存在。下面的代码。
您会注意到我有一堆不同的路径通过子进程调用独特的 python 函数。有趣的是,http 错误仅针对某些路径出现——通常是那些输出非常大的路径。在所有情况下,响应都会到达并在客户端呈现得很好,但是响应较大时,我会收到 http 错误并且我的应用程序会关闭。我可以想到一些潜在的 non-middleware 原因 - 可能 res.send() 随着响应变大而表现不同?或者可能是 subprocess.stdout 引起了较大响应的问题?或者,较长的响应时间可能会导致浏览器在响应交付之前重新发送请求?......想在深入研究潜在的中间件问题之前排除这些。谢谢
router.get('/element/chart', ensureAuthenticated, (req,res) => {
const path = require('path')
const {spawn} = require('child_process')
console.log(current_data_page_id)
console.log(typeof current_data_page_id)
let runScript;
runScript = (current_data_page_id) => {
switch(current_data_page_id) {
case "100":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_1.py')]);
break;
case "101":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_2.py')]);
break;
case "102":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_3.py')]);
break;
case "103":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_4.py')]);
break;
case "104":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_5.py')]);
break;
case "200":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_6.py')]);
break;
case "201":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_7.py')]);
break;
case "202":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_8.py')]);
break;
default:
console.log("Data page ID does not match current options")
};
};
const subprocess = runScript(current_data_page_id)
// print output of script
subprocess.stdout.on('data', (data) => {
var dataToSend = data.toString();
console.log(dataToSend);
res.send(dataToSend);
res.end('end')
return;
});
subprocess.stderr.on('data', (data) => {
console.log(`error:${data}`);
return;
});
subprocess.stderr.on('close', () => {
console.log("Closed");
return;
});
});
// ensureAuthenticated middleware
module.exports = {
ensureAuthenticated: function(req, res, next) {
if(req.isAuthenticated()) {
return next();
}
req.flash('error_msg', 'Please log in to view this resource');
res.sendFile(process.cwd() + '/views/login.html');
return;
}
}
控制台输出如下。堆栈跟踪指向“res.send(dataToSend);”行。
_http_outgoing.js:536
throw new ERR_HTTP_HEADERS_SENT('set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
错误的原因是你多次调用“结束”请求,一个http请求只需要完成一次。
您调用 res.send(dataToSend);
或 res.end('end')
这意味着您完成了 2 次请求。
当你删除 res.end('end');
行时,错误仍然出现,因为 res.send(dataToSend);
被调用了不止一次,因为我认为你的“python”命令多于 1 行的数据,那么 subprocess.stdout.on('data'
已经被调用了很多次。
这种情况的想法是在“命令”完成(完成)时结束请求,您可以使用 spawn
进程的 close
事件捕获“完成”事件(不是 subprocess.stdout
).
对于数据(命令的输出),我们有两种方式:
- 将输出附加到字符串变量并在命令完成后将其发送给客户端
var data = ''; // init data store
subprocess.stdout.on('data', (data) => {
var dataToSend = data.toString();
console.log(dataToSend);
data += dataToSend + '\n'; // append data with new line char :)
// res.send(dataToSend);
// res.end('end')
// return;
});
// subscribe to close event
subprocess.on('close', (code) => {
if (code !== 0) {
console.log(`grep process exited with code ${code}`);
}
res.send(data); // send data to client and finish the request
});
- 使用 express api 将响应写入
res
对象(我喜欢这种方式)
subprocess.stdout.on('data', (data) => {
var dataToSend = data.toString();
console.log(dataToSend);
res.write(dataToSend); // write data to response stream
// res.send(dataToSend);
// res.end('end')
// return;
});
// subscribe to close event
subprocess.on('close', (code) => {
if (code !== 0) {
console.log(`grep process exited with code ${code}`);
}
res.end(); // finish the request, `end` not `send`
});
运行 进入我的节点应用程序中有据可查的“错误 [ERR_HTTP_HEADERS_SENT]:将它们发送到客户端后无法设置 headers”。我已经查看了专门针对此问题的现有页面并尝试了他们的补救措施 - 主要是确保“return”所有其他响应;但是错误仍然存在。下面的代码。
您会注意到我有一堆不同的路径通过子进程调用独特的 python 函数。有趣的是,http 错误仅针对某些路径出现——通常是那些输出非常大的路径。在所有情况下,响应都会到达并在客户端呈现得很好,但是响应较大时,我会收到 http 错误并且我的应用程序会关闭。我可以想到一些潜在的 non-middleware 原因 - 可能 res.send() 随着响应变大而表现不同?或者可能是 subprocess.stdout 引起了较大响应的问题?或者,较长的响应时间可能会导致浏览器在响应交付之前重新发送请求?......想在深入研究潜在的中间件问题之前排除这些。谢谢
router.get('/element/chart', ensureAuthenticated, (req,res) => {
const path = require('path')
const {spawn} = require('child_process')
console.log(current_data_page_id)
console.log(typeof current_data_page_id)
let runScript;
runScript = (current_data_page_id) => {
switch(current_data_page_id) {
case "100":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_1.py')]);
break;
case "101":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_2.py')]);
break;
case "102":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_3.py')]);
break;
case "103":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_4.py')]);
break;
case "104":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_5.py')]);
break;
case "200":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_6.py')]);
break;
case "201":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_7.py')]);
break;
case "202":
return spawn('python', ["-u", path.join(process.cwd(),'/python/python_func_8.py')]);
break;
default:
console.log("Data page ID does not match current options")
};
};
const subprocess = runScript(current_data_page_id)
// print output of script
subprocess.stdout.on('data', (data) => {
var dataToSend = data.toString();
console.log(dataToSend);
res.send(dataToSend);
res.end('end')
return;
});
subprocess.stderr.on('data', (data) => {
console.log(`error:${data}`);
return;
});
subprocess.stderr.on('close', () => {
console.log("Closed");
return;
});
});
// ensureAuthenticated middleware
module.exports = {
ensureAuthenticated: function(req, res, next) {
if(req.isAuthenticated()) {
return next();
}
req.flash('error_msg', 'Please log in to view this resource');
res.sendFile(process.cwd() + '/views/login.html');
return;
}
}
控制台输出如下。堆栈跟踪指向“res.send(dataToSend);”行。
_http_outgoing.js:536
throw new ERR_HTTP_HEADERS_SENT('set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
错误的原因是你多次调用“结束”请求,一个http请求只需要完成一次。
您调用 res.send(dataToSend);
或 res.end('end')
这意味着您完成了 2 次请求。
当你删除 res.end('end');
行时,错误仍然出现,因为 res.send(dataToSend);
被调用了不止一次,因为我认为你的“python”命令多于 1 行的数据,那么 subprocess.stdout.on('data'
已经被调用了很多次。
这种情况的想法是在“命令”完成(完成)时结束请求,您可以使用 spawn
进程的 close
事件捕获“完成”事件(不是 subprocess.stdout
).
对于数据(命令的输出),我们有两种方式:
- 将输出附加到字符串变量并在命令完成后将其发送给客户端
var data = ''; // init data store
subprocess.stdout.on('data', (data) => {
var dataToSend = data.toString();
console.log(dataToSend);
data += dataToSend + '\n'; // append data with new line char :)
// res.send(dataToSend);
// res.end('end')
// return;
});
// subscribe to close event
subprocess.on('close', (code) => {
if (code !== 0) {
console.log(`grep process exited with code ${code}`);
}
res.send(data); // send data to client and finish the request
});
- 使用 express api 将响应写入
res
对象(我喜欢这种方式)
subprocess.stdout.on('data', (data) => {
var dataToSend = data.toString();
console.log(dataToSend);
res.write(dataToSend); // write data to response stream
// res.send(dataToSend);
// res.end('end')
// return;
});
// subscribe to close event
subprocess.on('close', (code) => {
if (code !== 0) {
console.log(`grep process exited with code ${code}`);
}
res.end(); // finish the request, `end` not `send`
});