Nodejs代理服务器发送到客户端后无法设置headers
Nodejs proxy server Cannot set headers after they are sent to the client
我正在尝试构建一个 Nodejs 服务器,该服务器从另一台包含数据的服务器获取数据,然后将其发送到客户端,我正在使用代理结构来处理多种类型的连接。
我正在使用 HTTP Express 服务器来处理 HTTP 请求,它在第一个请求之后的第一个请求中工作正常我有一个 Express 错误 Cannot set headers after they are sent to the
客户
_http_outgoing.js:526
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:526:11)
at ServerResponse.header (E:\Web\Projects\Color\server\node_modules\express\lib\response.js:771:10)
at ServerResponse.send (E:\Web\Projects\Color\server\node_modules\express\lib\response.js:170:12)
at EventEmitter.<anonymous> (E:\Web\Projects\Color\server\server.js:35:13)
at EventEmitter.emit (events.js:323:22)
at Socket.<anonymous> (E:\Web\Projects\Color\server\server.js:30:22)
at Socket.emit (events.js:323:22)
at addChunk (_stream_readable.js:294:12)
at readableAddChunk (_stream_readable.js:275:11)
at Socket.Readable.push (_stream_readable.js:209:10) {
code: 'ERR_HTTP_HEADERS_SENT'
}
我的 Express 服务器代码:
const express = require("express");
const net = require("net");
const http = require("http");
const login = require("./routes/auth");
const auth = require("./middlewares/verfication");
const info = require("./routes/info");
const events = require("events");
const eventEminter = new events.EventEmitter();
const app = express();
let clientSocket;
app.setClientSocket = (socket) => {
clientSocket = socket;
return true;
};
app.use(express.json());
app.use("/login", login);
app.use("/info", auth, info);
app.get("/", (req, res) => {
let clientData;
console.log("request has been made");
clientSocket.write("GET:/");
clientSocket.on("data", (data) => {
clientData = data.toString();
eventEminter.emit("ed");
console.log(clientData);
});
eventEminter.on("ed", () => {
res.send(clientData);
});
});
module.exports = app;
clientSocket变量表示与数据服务器的连接。
最后这是我的服务器代码:
const net = require("net");
const httpServer = require("./server");
//const clientServer = require("./client");
const dotenv = require("dotenv");
dotenv.config();
let clientSocket;
let registeredClient = false;
const proxyServer = net.createServer((socket) => {
socket.on("data", (data) => {
if (!data) {
socket.write("Error in request");
throw new Error("Request message is empty");
}
let request;
try {
request = data.toString();
} catch (error) {
console.log(
new Error("Request message can not be conveted to String")
);
throw error;
}
if (request.includes("HTTP")) {
const httpSocket = new net.Socket();
if (!registeredClient) {
registeredClient = httpServer.setClientSocket(clientSocket);
console.log("Client registered");
}
httpSocket.connect(4444, () => {
console.log("Proxy Connected to http server");
});
httpSocket.on("error", (err) => {
console.error("Proxy error: Could not connect to http server");
throw err;
});
const flushed = httpSocket.write(data, (err) => {
if (err) {
console.error(
"Proxy error :Could not send data to http server"
);
throw err;
}
});
// if (flushed) httpSocket.end();
let response;
httpSocket.on("data", (httpData) => {
if (!httpData) {
console.error(
"Proxy error: unable to retrive data from http server"
);
return;
}
socket.write(httpData.toString());
});
// httpSocket.on("end", () => {
// if (!response) {
// console.error(
// "Proxy error: unable to send response or empty response message"
// );
// return;
// }
// socket.write(response);
// });
} else {
if (!clientSocket) clientSocket = socket;
}
});
socket.on("error", (err) => {
console.error("Proxy error: could not connect with client");
});
});
const port = process.env.PORT || 4000;
proxyServer.listen(port, () => {
console.log(`Proxy Server is running on port ${port}`);
});
httpServer.listen(4444, () => {
console.log("Http server is running on port 4444");
});
感谢您的帮助。
您在每个“ed”事件上调用 res.send()
,并且在每个 clientSocket.on('data', ...)
事件上发出一个“ed”事件。因此,一旦您收到第二个 data
事件,您将尝试在同一响应中第二次调用 res.send()
。每个 http 请求只能得到一个响应。对于给定的 HTTP 响应,您不能多次调用 res.send()
。
目前还不清楚这段代码应该如何工作,因为我不知道你在这里真正想要完成什么。也许您需要从数据事件中积累所有数据,然后发送一个响应,然后解开所有侦听器,如果您没有再获得此请求的任何数据事件。或者,如果您想在第一个 data
事件上发送响应,则只需在发送响应后解除 data
和 ed
侦听器的挂钩。
请记住,在常规套接字上,您无法控制 data
事件中的数据。 TCP 是一种流协议,数据可以以任何大小的块形式出现,并且它到达的块可能与发送的块不完全相同。您通常必须自己寻找某种完整的数据包并且能够到 assemble 或将 data
事件分成完整的数据包,你可以用它来做一些事情。
通常,当您向服务器发送多个响应时,会出现“无法设置 headers 后它们被发送到客户端”的错误。在你的情况下,
eventEminter.on("ed", () => {
res.send(clientData);
});
当您使用它时,您正在向服务器发送多个响应。您应该只发送一次响应。您可以改用此代码
eventEminter.once('ed', () => {
res.send(clientData);
});
我正在尝试构建一个 Nodejs 服务器,该服务器从另一台包含数据的服务器获取数据,然后将其发送到客户端,我正在使用代理结构来处理多种类型的连接。 我正在使用 HTTP Express 服务器来处理 HTTP 请求,它在第一个请求之后的第一个请求中工作正常我有一个 Express 错误 Cannot set headers after they are sent to the 客户
_http_outgoing.js:526
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:526:11)
at ServerResponse.header (E:\Web\Projects\Color\server\node_modules\express\lib\response.js:771:10)
at ServerResponse.send (E:\Web\Projects\Color\server\node_modules\express\lib\response.js:170:12)
at EventEmitter.<anonymous> (E:\Web\Projects\Color\server\server.js:35:13)
at EventEmitter.emit (events.js:323:22)
at Socket.<anonymous> (E:\Web\Projects\Color\server\server.js:30:22)
at Socket.emit (events.js:323:22)
at addChunk (_stream_readable.js:294:12)
at readableAddChunk (_stream_readable.js:275:11)
at Socket.Readable.push (_stream_readable.js:209:10) {
code: 'ERR_HTTP_HEADERS_SENT'
}
我的 Express 服务器代码:
const express = require("express");
const net = require("net");
const http = require("http");
const login = require("./routes/auth");
const auth = require("./middlewares/verfication");
const info = require("./routes/info");
const events = require("events");
const eventEminter = new events.EventEmitter();
const app = express();
let clientSocket;
app.setClientSocket = (socket) => {
clientSocket = socket;
return true;
};
app.use(express.json());
app.use("/login", login);
app.use("/info", auth, info);
app.get("/", (req, res) => {
let clientData;
console.log("request has been made");
clientSocket.write("GET:/");
clientSocket.on("data", (data) => {
clientData = data.toString();
eventEminter.emit("ed");
console.log(clientData);
});
eventEminter.on("ed", () => {
res.send(clientData);
});
});
module.exports = app;
clientSocket变量表示与数据服务器的连接。 最后这是我的服务器代码:
const net = require("net");
const httpServer = require("./server");
//const clientServer = require("./client");
const dotenv = require("dotenv");
dotenv.config();
let clientSocket;
let registeredClient = false;
const proxyServer = net.createServer((socket) => {
socket.on("data", (data) => {
if (!data) {
socket.write("Error in request");
throw new Error("Request message is empty");
}
let request;
try {
request = data.toString();
} catch (error) {
console.log(
new Error("Request message can not be conveted to String")
);
throw error;
}
if (request.includes("HTTP")) {
const httpSocket = new net.Socket();
if (!registeredClient) {
registeredClient = httpServer.setClientSocket(clientSocket);
console.log("Client registered");
}
httpSocket.connect(4444, () => {
console.log("Proxy Connected to http server");
});
httpSocket.on("error", (err) => {
console.error("Proxy error: Could not connect to http server");
throw err;
});
const flushed = httpSocket.write(data, (err) => {
if (err) {
console.error(
"Proxy error :Could not send data to http server"
);
throw err;
}
});
// if (flushed) httpSocket.end();
let response;
httpSocket.on("data", (httpData) => {
if (!httpData) {
console.error(
"Proxy error: unable to retrive data from http server"
);
return;
}
socket.write(httpData.toString());
});
// httpSocket.on("end", () => {
// if (!response) {
// console.error(
// "Proxy error: unable to send response or empty response message"
// );
// return;
// }
// socket.write(response);
// });
} else {
if (!clientSocket) clientSocket = socket;
}
});
socket.on("error", (err) => {
console.error("Proxy error: could not connect with client");
});
});
const port = process.env.PORT || 4000;
proxyServer.listen(port, () => {
console.log(`Proxy Server is running on port ${port}`);
});
httpServer.listen(4444, () => {
console.log("Http server is running on port 4444");
});
感谢您的帮助。
您在每个“ed”事件上调用 res.send()
,并且在每个 clientSocket.on('data', ...)
事件上发出一个“ed”事件。因此,一旦您收到第二个 data
事件,您将尝试在同一响应中第二次调用 res.send()
。每个 http 请求只能得到一个响应。对于给定的 HTTP 响应,您不能多次调用 res.send()
。
目前还不清楚这段代码应该如何工作,因为我不知道你在这里真正想要完成什么。也许您需要从数据事件中积累所有数据,然后发送一个响应,然后解开所有侦听器,如果您没有再获得此请求的任何数据事件。或者,如果您想在第一个 data
事件上发送响应,则只需在发送响应后解除 data
和 ed
侦听器的挂钩。
请记住,在常规套接字上,您无法控制 data
事件中的数据。 TCP 是一种流协议,数据可以以任何大小的块形式出现,并且它到达的块可能与发送的块不完全相同。您通常必须自己寻找某种完整的数据包并且能够到 assemble 或将 data
事件分成完整的数据包,你可以用它来做一些事情。
通常,当您向服务器发送多个响应时,会出现“无法设置 headers 后它们被发送到客户端”的错误。在你的情况下,
eventEminter.on("ed", () => {
res.send(clientData);
});
当您使用它时,您正在向服务器发送多个响应。您应该只发送一次响应。您可以改用此代码
eventEminter.once('ed', () => {
res.send(clientData);
});