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?
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?
Respostas:
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.
404
, eo servidor de destino não recebe a solicitação ..
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);
}
})
http
e https
no meu caso, muito obrigado
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);
});
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);
});
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_proxy
variável de ambiente
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()
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
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".
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();
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"
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.');
}
});
Eu acho que existe uma alternativa melhor para as respostas a partir de 2019. Podemos usar o global-tunnel-ng
pacote para inicializar o proxy e não poluir o código http
ou com https
base em todos os lugares. Então, primeiro instale o global-tunnel-ng
pacote:
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
});
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.
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.
Para usar um proxy com https, tentei o conselho neste site (usando a dependência https-proxy-agent ) e funcionou para mim:
http://codingmiles.com/node-js-making-https-request-via-proxy/
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)=>{...});
Se você possui o esquema de autenticação http básica , é necessário criar uma string base64 myuser:mypassword
e 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.