I want to make an outgoing HTTP call from node.js, using the standard http.Client
. But I cannot reach the remote server directly from my network and need to go through a proxy.
How do I tell node.js to use the proxy?
I want to make an outgoing HTTP call from node.js, using the standard http.Client
. But I cannot reach the remote server directly from my network and need to go through a proxy.
How do I tell node.js to use the proxy?
Tim Macfarlane's answer was close with regards to using a HTTP proxy.
Using a HTTP proxy (for non secure requests) is very simple. You connect to the proxy and make the request normally except that the path part includes the full url and the host header is set to the host you want to connect to.
Tim was very close with his answer but he missed setting the host header properly.
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);
});
For the record his answer does work with http://nodejs.org/ but that's because their server doesn't care the host header is incorrect.
404
, and the destination server never receives the request.. –
Milburr vendor
modules which I also need to use the proxy connection. –
Hyperbolism options = { path: "http://www.example.com/", method: "GET", headers: {Host: "www.example.com"}}
. –
Chelate EDIT: As of Feb 11th 2020, request is fully deprecated. No new changes are expected.
You can use request, I just found it's unbelievably easy to use proxy on node.js, just with one external "proxy" parameter, even more it supports HTTPS through a http proxy.
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
and https
in my case, Thanks a lot –
Okoka headers: {'Proxy-Authorization': XXXX}
–
Sascha One thing that took me a while to figure out, use 'http' to access the proxy, even if you're trying to proxy through to a https server. This works for me using Charles (osx protocol analyser):
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);
});
I bought private proxy server, after purchase I got:
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
And I wanted to use it. First answer and second answer worked only for http(proxy) -> http(destination), however I wanted http(proxy) -> https(destination).
And for https destination it would be better to use HTTP tunnel directly. I found solution here.
Node v8:
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()
Node v14:
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
const agent = new https.Agent({ socket });
https.get({
host: 'www.kinopoisk.ru',
path: '/',
agent, // cannot use a default agent
}, (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();
socket
property isn't documented in nodejs. Was this option removed. –
Turves socket
option is not supported in http
modules' get
/ request
functions and simply gets ignored. –
Diplomatics Agent
with the socket specified. –
Pyroconductivity socket
property only works in HTTPS requests, because you can specify a socket when create a tls socket. See the tls.connect()
documentation. –
Lashaun As @Renat here already mentioned, proxied HTTP traffic comes in pretty normal HTTP requests. Make the request against the proxy, passing the full URL of the destination as the path.
var http = require ('http');
http.get ({
host: 'my.proxy.com',
port: 8080,
path: 'http://nodejs.org/'
}, function (response) {
console.log (response);
});
Thought I would add this module I found: https://www.npmjs.org/package/global-tunnel, which worked great for me (Worked immediately with all my code and third party modules with only the code below).
require('global-tunnel').initialize({
host: '10.0.0.10',
port: 8080
});
Do this once, and all http (and https) in your application goes through the proxy.
Alternately, calling
require('global-tunnel').initialize();
Will use the http_proxy
environment variable
The 'request' http package seems to have this feature:
https://github.com/mikeal/request
For example, the 'r' request object below uses localproxy to access its requests:
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)
}
})
Unfortunately there are no "global" defaults so that users of libs that use this cannot amend the proxy unless the lib pass through http options...
HTH, Chris
In case you need to the use basic authorisation for your proxy provider, just use the following:
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();
Basically you don't need an explicit proxy support. Proxy protocol is pretty simple and based on the normal HTTP protocol. You just need to use your proxy host and port when connecting with HTTPClient. Example (from node.js docs):
var http = require('http');
var google = http.createClient(3128, 'your.proxy.host');
var request = google.request('GET', '/',
{'host': 'www.google.com'});
request.end();
...
So basically you connect to your proxy but do a request to "http://www.google.com".
Node should support using the http_proxy environmental variable - so it is cross platform and works on system settings rather than requiring a per-application configuration.
Using the provided solutions, I would recommend the following:
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);
};
Usage To use the method, effectively just replace http.get, for instance the following writes the index page of google to a file called 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"
I think there a better alternative to the answers as of 2019. We can use the global-tunnel-ng
package to initialize proxy and not pollute the http
or https
based code everywhere. So first install global-tunnel-ng
package:
npm install global-tunnel-ng
Then change your implementations to initialize proxy if needed as:
const globalTunnel = require('global-tunnel-ng');
globalTunnel.initialize({
host: 'proxy.host.name.or.ip',
port: 8080
});
use 'https-proxy-agent' like this
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)=>{...});
Just run nodejs with proxy wrapper like tsocks tsocks node myscript.js
Original solution: Doing http requests through a SOCKS5 proxy in NodeJS
More info: https://www.binarytides.com/proxify-applications-with-tsocks-and-proxychains-on-ubuntu/
For windows: https://superuser.com/questions/319516/how-to-force-any-program-to-use-socks
May not be the exact one-liner you were hoping for but you could have a look at http://github.com/nodejitsu/node-http-proxy as that may shed some light on how you can use your app with http.Client.
Based on the answers from this thread it would seem like you could use proxychains
to run node.js through the proxy server:
$ proxychains /path/to/node application.js
Personally I wasnt able to install any of the proxychains versions on Cygwin/Windows environment so couldn't test it.
Furthermore, they also talked about using connect-proxy but I could not find any documentation on how to do this.
In short, I'm still stuck, but maybe someone can use this info to find a suitable work-around.
Imskull's answer almost worked for me, but I had to make some changes. The only real change is adding username, password, and setting rejectUnauthorized to false. I couldn't comment so I put this in an answer.
If you run the code it'll get you the titles of the current stories on Hacker News, per this 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.');
}
});
Only set the environment variable and the http
will use proxy.
const env = {
"host": "proxy.server.com.br",
"port": 8080,
"user": "my-user",
"pass": "my-pass"
};
process.env.http_proxy =
process.env.https_proxy =
`http://${env.user}:${env.pass}@${env.host}:${env.port}/`;
Axios has proxy option in its documentation.
Also you can define http_proxy
and https_proxy
environment variables
// `proxy` defines the hostname, port, and protocol of the proxy server.
// You can also define your proxy using the conventional `http_proxy` and
// `https_proxy` environment variables. If you are using environment variables
// for your proxy configuration, you can also define a `no_proxy` environment
// variable as a comma-separated list of domains that should not be proxied.
// Use `false` to disable proxies, ignoring environment variables.
// `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and
// supplies credentials.
// This will set an `Proxy-Authorization` header, overwriting any existing
// `Proxy-Authorization` custom headers you have set using `headers`.
// If the proxy server uses HTTPS, then you must set the protocol to `https`.
proxy: {
protocol: 'https',
host: '127.0.0.1',
port: 9000,
auth: {
username: 'mikeymike',
password: 'rapunz3l'
}
},
If you have the Basic http authentication scheme you have to make a base64 string of myuser:mypassword
, and then add "Basic" in the beginning. That's the value of Proxy-Authorization header, here an example:
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();
In nodejs you could use Buffer to encode
var encodedData = Buffer.from('myuser:mypassword').toString('base64');
console.log(encodedData);
Just as example, in browsers you could encode in base64 using btoa(), useful in ajax requests in a browser without proxy settings performing a request using proxy.
var encodedData = btoa('myuser:mypassword')
console.log(encodedData);
How to find wich scheme accepts the proxy server?
If we don't have a custom DNS configured (that would throw something like ERR_NAME_NOT_RESOLVED), when we perform a request, the response (code 407) should inform in the response headers which http authentication scheme the proxy is using.
© 2022 - 2024 — McMap. All rights reserved.