Отправка http-запросов через http-прокси-сервер в node.js

#node.js #http #https #proxy #http-proxy

#node.js #http #https #прокси #http-прокси

Вопрос:

Я пытаюсь отправить http (запросы GET и POST) на различные сайты для получения информации о заголовке / теле ответа, и мне нужно изменить, использую ли я прокси или нет. После того, как ранее не удалось использовать библиотеку restler для этой цели, я переключился на библиотеки узлов http и https для выполнения этих задач. Код следующим образом:

 /******/
//Http client libraries
var http = require("http");
var https = require("https");

//Request URL
var url = 'http://whatismyip.akamai.com';
//var url = 'https://en.wikipedia.org/wiki/Main_Page';

//Proxy config
var USE_PROXY = false;
var PROXY_PROTOCOL= 'http';
var PROXY_HOST= '127.0.0.1';
var PROXY_PORT= 6401;

/******/

//Define request options
var protocol = (USE_PROXY ? (PROXY_PROTOCOL == 'https' ? https : http) : (getProtocolFromUrl(url) == 'https' ? https : http));
var host = (USE_PROXY ? PROXY_HOST : getDomainFromUrl(url));
var port = (USE_PROXY ? PROXY_PORT : (getProtocolFromUrl(url) == 'https' ? 443 : 80));
var path = (USE_PROXY ? url : getPathFromUrl(url));

console.log('options.host = '   host);
console.log('options.port = '   port);
console.log('options.path = '   path);
console.log('n');

//Make the request
protocol.get({host: host, port: port, path: path}, function(res) {
    console.log('x-client-ip header: '   res.headers['x-client-ip']);
    console.log('Status code: '   res.statusCode);
    if ([301,302,303].indexOf(res.statusCode) > -1){
        console.log('location header : '   res.headers["location"]);
        console.log('Redirect url: '   combineUrls(res.headers["location"],url));
    } else {
        res.on('data', function (data) {
            console.log('Response body: '   data.toString());
        });
    }
}).on('error', function(err) {
    console.log(err);
});
  

В приведенном выше примере хост / порт / путь, указанные в параметрах запроса, определяются из URL-адреса и набора конфигурации прокси-сервера (как и использование библиотеки http или https). Чтобы проверить, что используются правильные настройки прокси-сервера, я проверяю IP-адрес запроса, считываемый хост-сервером, следующим образом:

  1. протокол http: тело ответа от http://whatismyip.akamai.com /
  2. протокол https: заголовок x-client-ip из https://en.wikipedia.org/wiki/Main_Page

При отсутствии установленного прокси-сервера это результаты:

1.

 options.host = whatismyip.akamai.com
options.port = 80
options.path = /

x-client-ip header: undefined
Status code: 200
Response body: **.**.**.** (public IP)
  
 options.host = en.wikipedia.org
options.port = 443
options.path = /wiki/Main_Page

x-client-ip header: **.**.**.** (public IP)
Status code: 200
Response body: <!DOCTYPE html> //etc...
  

Однако, если я попытаюсь использовать прокси-сервер (который маршрутизирует запросы через привязанное мобильное устройство и использует его мобильную сеть), я получаю следующие результаты:

1.

 options.host = 127.0.0.1
options.port = 6401
options.path = http://whatismyip.akamai.com

x-client-ip header: undefined
Status code: 400
Response body: <HTML><HEAD>
<TITLE>Invalid URL</TITLE>
</HEAD><BODY>
<H1>Invalid URL</H1>
The requested URL "httpamp;#58;amp;#47;whatismyipamp;#46;akamaiamp;#46;com", is invalid.<p>
Referenceamp;#32;amp;#35;9amp;#46;64fcff5aamp;#46;1605358006amp;#46;0
</BODY></HTML>
  
 options.host = 127.0.0.1
options.port = 6401
options.path = https://en.wikipedia.org/wiki/Main_Page

x-client-ip header: **.**.**.** (Proxy IP)
Status code: 301
location header : https://en.wikipedia.org/wiki/Main_Page
Redirect url: https://en.wikipedia.org/wiki/Main_Page
  

Таким образом, при использовании настроек прокси-сервера, похоже, возникают 2 проблемы — в первом запросе код ответа равен http400, а в теле указано, что указанный путь зашифрован. Странно то, что иногда я могу заставить его работать, если я перепишу код и жестко закодирую настройки, например:

 http.get({
    host: '127.0.0.1',
    port: 6401,
    path: 'http://whatismyip.akamai.com/'
}, function (res) {
    console.log('Status code: '   res.statusCode);
    res.on('data', function (data) {
        console.log('Response body: '   data.toString());
    });
});
  

вернет:

 Status code: 200
Response body: **.**.**.** (Proxy IP)
  

Поэтому в настоящее время я не могу объяснить, почему в предыдущем коде произошел сбой.

Во втором случае с протоколом https возвращается код ответа 301, но местоположение перенаправления совпадает с исходным URL-адресом, поэтому должна быть проблема со способом представления пути при пересылке запроса на хост-сервер.

*** Редактировать ***

Как и предлагалось, попробовал использовать другие библиотеки запросов. Пример с axios ниже:

 axios.get('https://en.wikipedia.org/wiki/Main_Page',{
    proxy: {
        host: '127.0.0.1',
        port: 6401
    }
}).then(function (res) {
    console.log(res.status);
    console.log(res.headers['x-client-ip']);
    //console.log(res.data);
}).catch(function (err) {
    console.log(err);
});
  

В этом случае вместо IP-адреса прокси-сервера был возвращен общедоступный IP-адрес.

Комментарии:

1. Почему вы не используете что-то вроде axios или got для выполнения запросов? Они оба поддерживают прокси

2. Нет причин, по которым я не могу переключиться, если я могу заставить любой из них работать. Я пробовал использовать axios, но он по-прежнему возвращает общедоступный IP-адрес вместо IP-адреса прокси-сервера — см. Редактирование исходного вопроса для кода.