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 事件上发送响应,则只需在发送响应后解除 dataed 侦听器的挂钩。

请记住,在常规套接字上,您无法控制 data 事件中的数据。 TCP 是一种流协议,数据可以以任何大小的块形式出现,并且它到达的块可能与发送的块不完全相同。您通常必须自己寻找某种完整的数据包并且能够到 assemble 或将 data 事件分成完整的数据包,你可以用它来做一些事情。

通常,当您向服务器发送多个响应时,会出现“无法设置 headers 后它们被发送到客户端”的错误。在你的情况下,

eventEminter.on("ed", () => {
        res.send(clientData);
    });

当您使用它时,您正在向服务器发送多个响应。您应该只发送一次响应。您可以改用此代码

eventEminter.once('ed', () => {
  res.send(clientData);
});