Quiero hacer una llamada HTTP saliente desde node.js, usando el estándar http.Client
. Pero no puedo acceder al servidor remoto directamente desde mi red y necesito pasar por un proxy.
¿Cómo le digo a node.js que use el proxy?
Quiero hacer una llamada HTTP saliente desde node.js, usando el estándar http.Client
. Pero no puedo acceder al servidor remoto directamente desde mi red y necesito pasar por un proxy.
¿Cómo le digo a node.js que use el proxy?
Respuestas:
La respuesta de Tim Macfarlane fue cercana con respecto al uso de un proxy HTTP.
Usar un proxy HTTP (para solicitudes no seguras) es muy simple. Se conecta al proxy y realiza la solicitud normalmente, excepto que la parte de la ruta incluye la url completa y el encabezado del host está configurado para el host al que desea conectarse.
Tim estuvo muy cerca con su respuesta, pero no pudo configurar el encabezado del host correctamente.
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 el registro, su respuesta funciona con http://nodejs.org/ pero eso se debe a que a su servidor no le importa que el encabezado del host sea incorrecto.
404
, y el servidor de destino no recibe la solicitud ..
Puede usar request , acabo de encontrar que es increíblemente fácil usar proxy en node.js, solo con un parámetro "proxy" externo, aún más es compatible con HTTPS a través de un 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
y https
en mi caso, muchas gracias
Una cosa que me llevó un tiempo descubrir, usar 'http' para acceder al proxy, incluso si está intentando conectarse a un servidor https. Esto funciona para mí usando Charles (analizador 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 @Renat ya mencionó aquí, el tráfico HTTP proxy viene en solicitudes HTTP bastante normales. Realice la solicitud contra el proxy, pasando la URL completa del destino como la ruta.
var http = require ('http');
http.get ({
host: 'my.proxy.com',
port: 8080,
path: 'http://nodejs.org/'
}, function (response) {
console.log (response);
});
Pensé que agregaría este módulo que encontré: https://www.npmjs.org/package/global-tunnel , que funcionó muy bien para mí (funcionó de inmediato con todo mi código y módulos de terceros con solo el código a continuación).
require('global-tunnel').initialize({
host: '10.0.0.10',
port: 8080
});
Haga esto una vez, y todos los http (y https) en su aplicación pasan por el proxy.
Alternativamente, llamando
require('global-tunnel').initialize();
Utilizará la http_proxy
variable de entorno.
Compré un servidor proxy privado, después de la compra obtuve:
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
Y quería usarlo. La primera respuesta y la segunda respuesta solo funcionaron para http (proxy) -> http (destino), sin embargo, quería http (proxy) -> https (destino).
Y para el destino https, sería mejor usar el túnel HTTP directamente. Encontré solución aquí . 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()
El paquete http 'request' parece tener esta característica:
https://github.com/mikeal/request
Por ejemplo, el objeto de solicitud 'r' a continuación utiliza localproxy para acceder a sus solicitudes:
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)
}
})
Desafortunadamente, no hay valores predeterminados "globales", por lo que los usuarios de las bibliotecas que usan esto no pueden modificar el proxy a menos que la lib pase a través de las opciones http ...
HTH, Chris
Básicamente no necesita un soporte de proxy explícito. El protocolo proxy es bastante simple y se basa en el protocolo HTTP normal. Solo necesita usar su host proxy y puerto cuando se conecta con HTTPClient. Ejemplo (de los documentos de 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();
...
Así que básicamente te conectas a tu proxy pero haces una solicitud a "http://www.google.com".
En caso de que necesite utilizar la autorización básica para su proveedor proxy, solo use lo siguiente:
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();
Node debe admitir el uso de la variable de entorno http_proxy, por lo que es multiplataforma y funciona en la configuración del sistema en lugar de requerir una configuración por aplicación.
Usando las soluciones proporcionadas, recomendaría lo siguiente:
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 el método, simplemente reemplace http.get, por ejemplo, lo siguiente escribe la página de índice de google en un archivo llamado 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"
La respuesta de Imskull casi funcionó para mí, pero tuve que hacer algunos cambios. El único cambio real es agregar nombre de usuario, contraseña y establecer el rechazo No autorizado en falso. No podía comentar, así que puse esto en una respuesta.
Si ejecuta el código, obtendrá los títulos de las historias actuales en Hacker News, según 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.');
}
});
Creo que hay una mejor alternativa a las respuestas a partir de 2019. Podemos usar el global-tunnel-ng
paquete para inicializar el proxy y no contaminar el código http
o el https
código basado en todas partes. Así que primero instale el global-tunnel-ng
paquete:
npm install global-tunnel-ng
Luego cambie sus implementaciones para inicializar el proxy si es necesario como:
const globalTunnel = require('global-tunnel-ng');
globalTunnel.initialize({
host: 'proxy.host.name.or.ip',
port: 8080
});
Es posible que no sea la línea exacta que esperaba, pero puede echar un vistazo a http://github.com/nodejitsu/node-http-proxy ya que eso puede arrojar algo de luz sobre cómo puede usar su aplicación con http. Cliente.
Según las respuestas de este hilo, parece que podría usar proxychains
para ejecutar node.js a través del servidor proxy:
$ proxychains /path/to/node application.js
Personalmente, no pude instalar ninguna de las versiones de proxychains en el entorno Cygwin / Windows , por lo que no pude probarlo.
Además, también hablaron sobre el uso de connect-proxy pero no pude encontrar ninguna documentación sobre cómo hacerlo.
En resumen, todavía estoy atascado, pero tal vez alguien pueda usar esta información para encontrar una solución adecuada.
Para usar un proxy con https probé los consejos en este sitio web (usando la dependencia https-proxy-agent ) y funcionó para mí:
http://codingmiles.com/node-js-making-https-request-via-proxy/
use 'https-proxy-agent' como este
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)=>{...});
Si tiene el esquema de autenticación HTTP básico, debe crear una cadena base64 myuser:mypassword
y luego agregar "Básico" al principio. Ese es el valor del encabezado Proxy-Authorization , aquí un ejemplo:
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();
En nodejs puedes usar Buffer para codificar
var encodedData = Buffer.from('myuser:mypassword').toString('base64');
console.log(encodedData);
Como ejemplo, en los navegadores puede codificar en base64 usando btoa () , útil en solicitudes ajax en un navegador sin configuraciones de proxy que realicen una solicitud usando proxy.
var encodedData = btoa('myuser:mypassword')
console.log(encodedData);
¿Cómo encontrar qué esquema acepta el servidor proxy?
Si no tenemos un DNS personalizado configurado (que arrojaría algo como ERR_NAME_NOT_RESOLVED), cuando realizamos una solicitud, la respuesta (código 407) debería informar en los encabezados de respuesta qué esquema de autenticación http está usando el proxy.