-
Notifications
You must be signed in to change notification settings - Fork 7.3k
HTTPS request not working with proxy #2474
Comments
I think that you should use CONNECT method with HTTP (not HTTPS) if you want to use end-to-end HTTPS through a proxy. Unfortunately, Node does not support it well. |
Okay, thanks for the pointer. I played some more with this. I made a simple tcp echo server, which just passes along requests to the squid proxy, like so: var net = require('net');
net.createServer(function (upstream) {
var downstream = net.connect(3128, function () {
upstream.on('data', function (data) {
console.log(data.toString());
downstream.write(data);
});
upstream.on('end', function () {
downstream.end();
});
});
downstream.on('data', function (data) {
upstream.write(data);
});
downstream.on('end', function () {
upstream.end();
});
}).listen(3000); This logs the request so I can see what request headers my browser sends for https through a proxy. All the browser does is send the following headers (for https://www.google.com):
Logically then I could reproduce these in node like so: var http = require('http');
var options = {
hostname: '127.0.0.1',
port: 3128,
path: 'www.google.com:443',
headers: {
'User-Agent': 'Node.js/0.6.6',
'Proxy-Connections': 'keep-alive',
'Host': 'www.google.com'
},
method: 'CONNECT'
};
var req = http.request(options, function (res) {
console.log('statusCode: ', res.statusCode);
console.log('headers: ', res.headers);
res.on('data', function (chunk) {
process.stdout.write(chunk);
});
}).on('error', function (e) {
console.error(e);
}).end(); It gives me a statusCode 411 from squid now. Per squid, it received the following headers:
It seems to me that the Why is node nuking my |
@chowey - Probably, squid displays a path without host/port. Actually, Node sends valid request line:
The problem may be - 'Host': 'www.google.com'
+ 'Host': 'www.google.com',
+ `Content-Length`: 0 result:
I think that Node should not add |
I figured you might use
they just overwrite any createConnection I provide. It isn't like that for the http module. If they did something instead like:
then I could provide a custom socket. My createConnection formula might be something like: function createConnection(port, host, options) {
var socket = net.connect(port, host, function () {
socket.write('CONNECT www.google.com:443 HTTP/1.1\r\n' +
'User-Agent: Node.js/0.6.6\r\n' +
'Proxy-Connections: keep-alive\r\n' +
'Host: www.google.com\r\n\r\n',
function () {
return socket;
});
});
} (probably this function needs more work, but you get the idea.) |
I have noticed that http-parser handles CONNECT method request as a Upgrade request. So, we can handle it using |
@bnoordhuis - Can you review koichik/node@47adb2e and koichik/node@a635acb? |
@koichik: I don't really like the concept, it adds a lot of extra API for a relatively minor issue. What are the alternatives? |
@bnoordhuis - Thanks for the suggestion, how about like this: var req = https.get({
host: 'github.com',
...
agent: new https.Agent({ // HTTPS
httpTunnel: { // over HTTP
host: 'localhost',
port: 3128
}
}
}, function(res) {
...
}); Or, should not Agent support tunneling? |
That looks much simpler.
I'm undecided. Yes, because HTTP is a first class citizen in Node. No, because tunneling is complex. You start with simple CONNECT support, next thing you know you'll need to add various authentication methods, SOCKS, DNS-over-SOCKS, workarounds for proxy bugs, etc. @isaacs, @piscisaureus, @ry: What do you think? |
If I can add my $0.02, if the authentication methods, etc. etc. can be done in userland, then they can be done in userland. The problem with CONNECT support was it could not be done in userland because the node core's http/https modules did not really permit it. I don't know if the Agent support is really too much "fluff" above the node core, but I don't think it will create a snowball effect of needing to support proxy bugs, etc. Because all that complexity stuff, if the core API is solid and adaptable, can be pushed off to userland. |
@chowey - Sorry for the delay, with current master you can use HTTPS via proxy like this: var http = require('http');
var https = require('https');
var connectReq = http.request({ // establishing a tunnel
host: 'localhost',
port: 3128,
method: 'CONNECT',
path: 'github.com:443',
}).on('connect', function(res, socket, head) {
// should check res.statusCode here
var req = https.get({
host: 'github.com',
socket: socket, // using a tunnel
agent: false // cannot use a default agent
}, function(res) {
res.setEncoding('utf8');
res.on('data', console.log);
});
}).end(); So, Agent support may not be MUST... |
Wow, excellent. |
Here's my $0.02: Patch @mikeal's request lib to support this kind of tunneling with the same API that it uses for http->http or https->https proxying. I would like this to Just Work for npm anyway, and I think he'd probably accept a pull req to make it work. If the requests for this go away, great. If something is blocked there, then we can discuss how to address that. The benefit of doing it in userland is that we can have the feature much sooner and experiment on it faster. For 0.7, we can discuss the best api to pull in proxying, if necessary. I quite like request's approach of doing:
Maybe we could add a "proxy" member to the config object that gets passed to http.request and https.request. But that can't land sooner than 0.7, of course, and it might even be a good idea to put it off until 0.8 if we uncover issues with it. |
yes, i'll accept a pull request that adds support for https proxies. On Jan 13, 2012, at January 13, 201210:47 AM, Isaac Z. Schlueter wrote:
|
@koichik Is this feature going to be interagted into v0.6.x? |
@isaacs, @mikeal - Thanks, some blockers have already fixed in c1a63a9, 08a91ac and 7dffbaf. The CONNECT method works now. Okay, Let's move Agent support to userland. I will send a PR to @mikeal's request or create a new module. @tjanczuk - No, because the patches change some behavior, especially the event emitted by a CONNECT method was changed into Closing. |
Is it just me or is the current master failing to build? |
@chowey - Please try:
|
Alas I am using Winblows 7 with VC++ Express. |
I get the following error:
What's this isolates business all about? |
No worries, found the solution in #2452:
|
I was wondering if the proxy settings should be hard coded. |
I have this same issue with my proxies (buycheapproxies.org). I was never able to use them with nodejs with the code that worked perfectly with other proxies (fineproxy.org). I tried @koichik code above but got socket hung up when used www.mysite.com:443 as path in the CONNECT request but when I use mysite.com:443 (ie. without www), requests gets successful but I get a different version of the website that doesn't match with what it looks in the browser. Same proxies work perfectly fine in the chrome and curl but not in the node.js. My Node.js version is 7.x. Can somebody guide in the correct direction ? |
I have a squid proxy on my local computer (127.0.0.1:3128). It is configured to require no authentication. If I try to use an
https.request
, I get an error like:The following code reproduces this issue (provided of course that you have a squid proxy set up on port 3128):
It is definitely an error with node itself. If the problem were with squid, it would just result in responses with statusCode 501.
I am running v0.6.6 on Windows 7.
The text was updated successfully, but these errors were encountered: