Como posso usar um proxy http com node.js http.Client?

137

Desejo fazer uma chamada HTTP de saída do node.js, usando o padrão http.Client. Mas não consigo acessar o servidor remoto diretamente da minha rede e preciso passar por um proxy.

Como eu digo ao node.js para usar o proxy?

Christian Berg
fonte
1
Estou tendo o mesmo problema. O Node.js está protegido por um firewall e não consigo criar um HTTPClient para um site externo.
ddallala

Respostas:

153

A resposta de Tim Macfarlane foi próxima no que diz respeito ao uso de um proxy HTTP.

Usar um proxy HTTP (para solicitações não seguras) é muito simples. Você se conecta ao proxy e faz a solicitação normalmente, exceto que a parte do caminho inclui a URL completa e o cabeçalho do host é definido como o host ao qual você deseja se conectar.
Tim estava muito próximo de sua resposta, mas não conseguiu definir o cabeçalho do host corretamente.

var http = require("http");

var options = {
  host: "proxy",
  port: 8080,
  path: "http://www.google.com",
  headers: {
    Host: "www.google.com"
  }
};
http.get(options, function(res) {
  console.log(res);
  res.pipe(process.stdout);
});

Para o registro, sua resposta funciona com http://nodejs.org/, mas é porque o servidor deles não se importa com o cabeçalho do host está incorreto.

Samuel
fonte
1
Existe uma maneira de usar a porta https de conexão proxy proxy http? parece que não tem um método fácil
Gohan
@Gohan Veja a resposta de Chris abaixo para obter um exemplo de como conectar-se a um servidor https através de um proxy http.
HairOfTheDog 19/07/12
se você receber uma solicitação incorreta, coloque o caminho: '/'
Laurent Debricon
9
Como posso integrar usuário proxy e senha proxy no bloco de opções?
Twistleton
Isso mudou? Mesmo com o destino final como outro servidor local, eu recebo um 404, eo servidor de destino não recebe a solicitação ..
OJFord
53

Você pode usar request , acabei de descobrir que é incrivelmente fácil usar proxy no node.js, apenas com um parâmetro "proxy" externo, e ainda mais, ele suporta HTTPS através de um proxy http.

var request = require('request');

request({
  'url':'https://anysite.you.want/sub/sub',
  'method': "GET",
  'proxy':'http://yourproxy:8087'
},function (error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(body);
  }
})
Imskull
fonte
1
Trabalhou para ambos httpe httpsno meu caso, muito obrigado
Samuel Bushi
Alguma idéia de por que isso não funciona em páginas corporativas internas?
Keinabel 3/07
1
Estou surpreso que páginas internas da corporação estejam protegidas por um proxy. Você tem certeza de que o proxy não está sendo ignorado para páginas internas? Está em uma vlan diferente?
Chanoch
U precisa especificar a autenticação de alguma forma (vou postar aqui se eu descobrir isso)
Igor L.
Eu recebi este erro usando a solicitação com proxy: Erro: o soquete de encapsulamento não pôde ser estabelecido, causa = connect ECONNREFUSED 127.0.0.1:80
Federico Caccia
35

Uma coisa que demorei um pouco para descobrir, use 'http' para acessar o proxy, mesmo se você estiver tentando fazer um proxy para um servidor https. Isso funciona para mim usando Charles (analisador de protocolo osx):

var http = require('http');

http.get ({
    host: '127.0.0.1',
    port: 8888,
    path: 'https://www.google.com/accounts/OAuthGetRequestToken'
}, function (response) {
    console.log (response);
});
Chris
fonte
1
O código acima não está funcionando para mim e está relacionado ao problema github.com/joyent/node/issues/2474 verifique a resposta do koichik, precisamos usar "method": "connect" e no evento "connect", enviamos as informações do caminho .
Palani
16

Como o @Renat aqui já mencionado, o tráfego HTTP proxy vem em solicitações HTTP bastante normais. Faça a solicitação no proxy, passando o URL completo do destino como o caminho.

var http = require ('http');

http.get ({
    host: 'my.proxy.com',
    port: 8080,
    path: 'http://nodejs.org/'
}, function (response) {
    console.log (response);
});
Tim Macfarlane
fonte
2
Isso parece funcionar, embora Fiddler chama de uma violação do protocolo que sugere que não é um HTTP adequada pedido-via-proxy ...
Marc
11

Pensei em adicionar este módulo que encontrei: https://www.npmjs.org/package/global-tunnel , que funcionou muito bem para mim (trabalhei imediatamente com todos os meus códigos e módulos de terceiros, apenas com o código abaixo).

require('global-tunnel').initialize({
  host: '10.0.0.10',
  port: 8080
});

Faça isso uma vez e todos os http (e https) do seu aplicativo passarão pelo proxy.

Como alternativa, chamando

require('global-tunnel').initialize();

Usará a http_proxyvariável de ambiente

major-mann
fonte
2
Isso funcionou para mim! Na verdade, dessa maneira, você desacopla o proxy do código e usa a configuração existente para o npm! que é o caminho a percorrer, eu diria
cesaregb
@NeelBasu Sim, é verdade
major-mann
10

Comprei um servidor proxy privado, após a compra recebi:

255.255.255.255 // IP address of proxy server
99999 // port of proxy server
username // authentication username of proxy server
password // authentication password of proxy server

E eu queria usá-lo. A primeira e a segunda resposta funcionaram apenas para http (proxy) -> http (destino), no entanto, eu queria http (proxy) -> https (destino).

E para o destino https, seria melhor usar o túnel HTTP diretamente. Encontrei solução aqui . Código final:

const http = require('http')
const https = require('https')
const username = 'username'
const password = 'password'
const auth = 'Basic ' + Buffer.from(username + ':' + password).toString('base64')

http.request({
  host: '255.255.255.255', // IP address of proxy server
  port: 99999, // port of proxy server
  method: 'CONNECT',
  path: 'kinopoisk.ru:443', // some destination, add 443 port for https!
  headers: {
    'Proxy-Authorization': auth
  },
}).on('connect', (res, socket) => {
  if (res.statusCode === 200) { // connected to proxy server
    https.get({
      host: 'www.kinopoisk.ru',
      socket: socket,    // using a tunnel
      agent: false,      // cannot use a default agent
      path: '/your/url'  // specify path to get from server
    }, (res) => {
      let chunks = []
      res.on('data', chunk => chunks.push(chunk))
      res.on('end', () => {
        console.log('DONE', Buffer.concat(chunks).toString('utf8'))
      })
    })
  }
}).on('error', (err) => {
  console.error('error', err)
}).end()
Alexey Volodko
fonte
7

O pacote http 'request' parece ter este recurso:

https://github.com/mikeal/request

Por exemplo, o objeto de solicitação 'r' abaixo usa localproxy para acessar suas solicitações:

var r = request.defaults({'proxy':'http://localproxy.com'})

http.createServer(function (req, resp) {
  if (req.url === '/doodle.png') {
    r.get('http://google.com/doodle.png').pipe(resp)
  }
})

Infelizmente, não há padrões "globais" para que os usuários das bibliotecas que usam isso não possam alterar o proxy, a menos que a biblioteca passe pelas opções http ...

HTH, Chris

Chris Kimpton
fonte
o pacote http de solicitação facilita a alternância do código entre o uso de proxy e não proxy (o que é bastante útil no meu laptop).
Jon Madison
5

Basicamente, você não precisa de um suporte explícito ao proxy. O protocolo de proxy é bastante simples e baseado no protocolo HTTP normal. Você só precisa usar o host e a porta do proxy ao se conectar ao HTTPClient. Exemplo (dos documentos node.js):

var http = require('http');
var google = http.createClient(3128, 'your.proxy.host');
var request = google.request('GET', '/',
  {'host': 'www.google.com'});
request.end();
...

Então, basicamente, você se conecta ao seu proxy, mas faz uma solicitação para "http://www.google.com".

Renat
fonte
3
http.createClient está obsoleto, Tim Macfarlane está usando o http.get mais recente abaixo
sami
1
Aparentemente, isso não funcionará mais com o node.js a partir da v5.6, pois eles removeram o createClient .
Marc
5

Caso você precise usar a autorização básica para o seu provedor proxy, use o seguinte:

var http = require("http");

var options = {
    host:       FarmerAdapter.PROXY_HOST,
    port:       FarmerAdapter.PROXY_PORT,
    path:       requestedUrl,
    headers:    {
        'Proxy-Authorization':  'Basic ' + new Buffer(FarmerAdapter.PROXY_USER + ':' + FarmerAdapter.PROXY_PASS).toString('base64')
    }
};

var request = http.request(options, function(response) {
    var chunks = [];
    response.on('data', function(chunk) {
        chunks.push(chunk);
    });
    response.on('end', function() {
        console.log('Response', Buffer.concat(chunks).toString());
    });
});

request.on('error', function(error) {
    console.log(error.message);
});

request.end();
Vyacheslav Voronchuk
fonte
1
onde posso encontrar "FarmerAdapter"?
1828 Alex
3

O nó deve suportar o uso da variável de ambiente http_proxy - para que ela seja multiplataforma e funcione nas configurações do sistema, em vez de exigir uma configuração por aplicativo.

Usando as soluções fornecidas, eu recomendaria o seguinte:

Coffeescript

get_url = (url, response) ->
  if process.env.http_proxy?
    match = process.env.http_proxy.match /^(http:\/\/)?([^:\/]+)(:([0-9]+))?/i
    if match
      http.get { host: match[2], port: (if match[4]? then match[4] else 80), path: url }, response
      return
  http.get url, response

Javascript

get_url = function(url, response) {
  var match;
  if (process.env.http_proxy != null) {
    match = process.env.http_proxy.match(/^(http:\/\/)?([^:\/]+)(:([0-9]+))?/i);
    if (match) {
      http.get({
        host: match[2],
        port: (match[4] != null ? match[4] : 80),
        path: url
      }, response);
      return;
    }
  }
  return http.get(url, response);
};

Uso Para usar o método, substitua efetivamente http.get, por exemplo, o seguinte grava a página de índice do google em um arquivo chamado test.htm:

file = fs.createWriteStream path.resolve(__dirname, "test.htm")
get_url "http://www.google.com.au/", (response) ->
  response.pipe file
  response.on "end", ->
    console.log "complete"
Lucas
fonte
A configuração de http_proxy não parece ter efeito ao executar o Node no Windows.
precisa saber é o seguinte
Ele deve funcionar no Windows (que é o sistema principal que estou usando). Depois de definir a configuração, reinicie a sessão do terminal (se configurada através do painel de controle e não configurada). Você deve poder verificar se está configurado corretamente usando o eco% HTTP_PROXY% Ou, melhor ainda, você deve usar o próprio nó node -e "console.log (process.env.http_proxy);" Isso funcionou para mim no Windows, então boa sorte.
Lucas
1

A resposta de Imskull quase funcionou para mim, mas tive que fazer algumas alterações. A única mudança real é adicionar nome de usuário, senha e definir rejectUnauthorized para false. Não pude comentar, então coloquei isso em resposta.

Se você executar o código, obterá os títulos das histórias atuais no Hacker News, de acordo com este tutorial: http://smalljs.org/package-managers/npm/

var cheerio = require('cheerio');
var request = require('request');

request({
    'url': 'https://news.ycombinator.com/',
    'proxy': 'http://Username:Password@YourProxy:Port/',
    'rejectUnauthorized': false
}, function(error, response, body) {
    if (!error && response.statusCode == 200) {
        if (response.body) {
            var $ = cheerio.load(response.body);
            $('td.title a').each(function() {
                console.log($(this).text());
            });
       }
    } else {
        console.log('Error or status not equal 200.');
    }
});
Vasily Kushakov
fonte
1

Eu acho que existe uma alternativa melhor para as respostas a partir de 2019. Podemos usar o global-tunnel-ngpacote para inicializar o proxy e não poluir o código httpou com httpsbase em todos os lugares. Então, primeiro instale o global-tunnel-ngpacote:

npm install global-tunnel-ng

Em seguida, altere suas implementações para inicializar o proxy, se necessário, como:

const globalTunnel = require('global-tunnel-ng');

globalTunnel.initialize({
  host: 'proxy.host.name.or.ip',
  port: 8080
});
portador de anel
fonte
0

Pode não ser a única linha exata que você esperava, mas você pode dar uma olhada em http://github.com/nodejitsu/node-http-proxy, pois isso pode lançar alguma luz sobre como você pode usar seu aplicativo com http. Cliente.

vida cheia
fonte
1
Como isso é útil?
Jerinaw 13/05/19
0

http://groups.google.com/group/nodejs/browse_thread/thread/d5aadbcaa00c3f7/12ebf01d7ec415c3?lnk=gst&q=proxy#12ebf01d7ec415c3

Com base nas respostas deste segmento, parece que você poderia usar proxychains para executar o node.js através do servidor proxy:
$ proxychains /path/to/node application.js

Pessoalmente, não consegui instalar nenhuma das versões de proxychains no ambiente Cygwin / Windows , portanto não pude testá-lo.

Além disso, eles também falaram sobre o uso do proxy de conexão, mas não encontrei nenhuma documentação sobre como fazer isso.

Em suma, ainda estou preso, mas talvez alguém possa usar essas informações para encontrar uma solução alternativa adequada.

ddallala
fonte
update: após algumas investigações, descobri que não era possível criar proxychains no CygWin porque RTLD_NEXT não é suportado.
ddallala
0

use 'https-proxy-agent' assim

var HttpsProxyAgent = require('https-proxy-agent');
var proxy = process.env.https_proxy || 'other proxy address';
var agent = new HttpsProxyAgent(proxy);

options = {
    //...
    agent : agent
}

https.get(options, (res)=>{...});
Verde ruim
fonte
0

Se você possui o esquema de autenticação http básica , é necessário criar uma string base64 myuser:mypassworde adicionar "Básico" no início. Esse é o valor do cabeçalho de autorização de proxy , aqui está um exemplo:

var Http = require('http');

var req = Http.request({
    host: 'myproxy.com.zx',
    port: 8080,
    headers:{"Proxy-Authorization": "Basic bXl1c2VyOm15cGFzc3dvcmQ="},
    method: 'GET',
    path: 'http://www.google.com/'
    }, function (res) {
        res.on('data', function (data) {
        console.log(data.toString());
    });
});

req.end();

No nodejs, você pode usar o Buffer para codificar

var encodedData = Buffer.from('myuser:mypassword').toString('base64');

console.log(encodedData);

Da mesma forma que nos navegadores, você pode codificar em base64 usando btoa () , útil em solicitações ajax em um navegador sem que as configurações de proxy realizem uma solicitação usando proxy.

var encodedData = btoa('myuser:mypassword')

console.log(encodedData);

Como encontrar qual esquema aceita o servidor proxy?

Se não tivermos um DNS personalizado configurado (que geraria algo como ERR_NAME_NOT_RESOLVED), quando executarmos uma solicitação, a resposta (código 407) deverá informar nos cabeçalhos de resposta qual esquema de autenticação HTTP o proxy está usando.

Emeeus
fonte