Создание прокси-сервера Node js с несколькими целями в зависимости от тела запроса

#node.js #proxy

#node.js #прокси

Вопрос:

Мне нужно создать прокси-сервер Node js, который в зависимости от содержимого в теле будет перенаправлять на тот или иной сервер.

Пример: я отправляю запрос на сервер 127.0.0.1:8080 с данными {«tag»: «server_1»}. Этот сервер будет считывать данные, и если тег «server_1», то он отправляет запрос на сервер 127.0.0.1:8081, в противном случае запрос отправляется на 127.0.0.1:8082.

Я начал создавать прокси, но я не могу изменить имя хоста, порт и протокол в соответствии с полученными данными.

Вот мой код:

 const http = require('http');
const https = require('https');

const proxyHostname = '0.0.0.0';
const proxyPort = 8080;

const primaryServerProtocol = "http";
const primaryServerHostname = "127.0.0.1";
const primaryServerPort = 8081;

const secondaryServerProtocol = "https";
const secondaryServerHostname = "127.0.0.1";
const secondaryServerPort = 8082;

const proxyServer = http.createServer((clientRequest, clientResponse) => {
    const serverRequestOptions = {
        hostname: primaryServerHostname,
        port: primaryServerPort,
        path: clientRequest.url,
        method: clientRequest.method,
        headers: clientRequest.headers,
        rejectUnauthorized: false
    }
    
    /***********************
    let data = [];
    clientRequest.on('data', function (chunk) {
        data.push(chunk);
    });

    clientRequest.on('end', function () {
        data = Buffer.concat(data).toString();

        if (data.includes("server_2")) {
            // Set options...
        }
    });
    ***********************/

    const proxy = https.request(serverRequestOptions, (serverResponse) => {
        clientResponse.writeHead(serverResponse.statusCode, serverResponse.headers);
        serverResponse.pipe(clientResponse, {
            end: true
        });
    });

    clientRequest.pipe(proxy, {
        end: true
    });
});

proxyServer.listen(proxyPort, proxyHostname, () => {
    console.log(`Server running at http://${proxyHostname}:${proxyPort}`);
});
  

Я также пробовал использовать http-proxy, но я предпочитаю ванильное решение, но я не совсем понимаю, как каналы работают в моем случае.

 const http = require('http');
const httpProxy = require('http-proxy');

const proxyHostname = '0.0.0.0';
const proxyPort = 8080;

const primaryServerProtocol = "http:";
const primaryServerHostname = "127.0.0.1";
const primaryServerPort = 8081;

const secondaryServerProtocol = "https:";
const secondaryServerHostname = "127.0.0.1";
const secondaryServerPort = 8082;

const options = {
    target: {
        protocol: primaryServerProtocol,
        host: primaryServerHostname,
        port: primaryServerPort,
    },
    secure: false
};

const proxy = httpProxy.createProxyServer();

const proxyServer = http.createServer((req, res) => {
    proxy.web(req, res, options);
});

/***********************
proxy.on('proxyReq', (proxyReq, req) => {
    let data = '';

    req.on('data', chunk => {
        data  = chunk;
    });

    req.on('end', () => {
        if (data.includes("server_2")) {
            // Set options...
        }
    });
});
***********************/

proxyServer.listen(proxyPort, proxyHostname, () => {
    console.log(`Server running at http://${proxyHostname}:${proxyPort}`);
});
  

Этот код работает, но отправляется на правильный сервер с запросом задержки …
У вас есть идея или решение?

Ответ №1:

Я публикую свое решение для тех, кому может быть интересно :

 const http = require('http');
const https = require('https');

const proxyHostname = '0.0.0.0';
const proxyPort = 8080;

const primaryServerHostname = "127.0.0.1";
const primaryServerPort = 8081;

const secondaryServerHostname = "127.0.0.1";
const secondaryServerPort = 8082;

const proxyServer = http.createServer((clientRequest, clientResponse) => {
    const serverRequestOptions = {
        path: clientRequest.url,
        method: clientRequest.method,
        headers: clientRequest.headers,
        rejectUnauthorized: false
    }

    let requestBody = [];
    clientRequest.on('data', (chunk) => {
        requestBody.push(chunk);
    });

    clientRequest.on('end', () => {
        requestBody = Buffer.concat(requestBody).toString();

        if (requestBody.includes("server_2")) {
            serverRequestOptions.hostname = secondaryServerHostname;
            serverRequestOptions.port = secondaryServerPort;
        } else {
            serverRequestOptions.hostname = primaryServerHostname;
            serverRequestOptions.port = primaryServerPort;
        }

        const proxy = https.request(serverRequestOptions, (serverResponse) => {
            clientResponse.writeHead(serverResponse.statusCode, serverResponse.headers);
            serverResponse.pipe(clientResponse);
        });

        proxy.on('error', (err) => {
            console.error(err);
            clientResponse.statusCode = 500;
            clientResponse.end(err.message);
        });
    
        proxy.write(requestBody);
        proxy.end();
    });

    clientRequest.on('error', (err) => {
        console.error(err);
        clientResponse.statusCode = 400;
        clientResponse.end(err.message);
    });
    
    clientResponse.on('error', (err) => {
        console.error(err);
        clientResponse.end(err.message);
    });
});

proxyServer.listen(proxyPort, proxyHostname, () => {
    console.log(`Server running at http://${proxyHostname}:${proxyPort}`);
});