Last active
October 21, 2024 05:02
-
-
Save TooTallNate/5952254 to your computer and use it in GitHub Desktop.
Node.js `http.Agent` class implementations...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Module dependencies. | |
*/ | |
var net = require('net'); | |
var inherits = require('util').inherits; | |
var EventEmitter = require('events').EventEmitter; | |
/** | |
* Module exports. | |
*/ | |
module.exports = Agent; | |
/** | |
* Base HTTP "Agent" class. Emulates the node-core `http.Agent` class, but | |
* implemented in a way that can be easily extended for additional functionality. | |
* | |
* This base implementation does no socket pooling, and opens | |
* a new connection for every HTTP request. | |
* | |
* It behaves more-or-less like `agent: false`. | |
* | |
* @api public | |
*/ | |
function Agent () { | |
if (!(this instanceof Agent)) return new Agent(); | |
EventEmitter.call(this); | |
} | |
inherits(Agent, EventEmitter); | |
/** | |
* Default port to connect to. | |
*/ | |
Agent.prototype.defaultPort = 80; | |
/** | |
* Called by node-core's "_http_client.js" module when creating a new HTTP request | |
* with this Agent instance. | |
* | |
* @api public | |
*/ | |
Agent.prototype.addRequest = function (req, host, port, localAddress) { | |
var opts; | |
if ('object' == typeof host) { | |
// >= v0.11.x API | |
opts = host; | |
} else { | |
// <= v0.10.x API | |
opts = { | |
host: host, | |
port: port, | |
localAddress: localAddress | |
}; | |
} | |
// hint to use "Connection: close" | |
req.shouldKeepAlive = false; | |
// create the `net.Socket` instance | |
var info = { | |
host: opts.hostname || opts.host, | |
port: +opts.port || this.defaultPort, | |
localAddress: opts.localAddress | |
}; | |
this.createConnection(info, function (err, socket) { | |
if (err) { | |
req.emit('error', err); | |
} else { | |
req.onSocket(socket); | |
} | |
}); | |
}; | |
/** | |
* Creates and returns a `net.Socket` instance to use for an HTTP request. | |
* | |
* @api public | |
*/ | |
Agent.prototype.createConnection = function (opts, fn) { | |
var socket = net.connect(opts); | |
fn(null, socket); | |
return socket; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Module dependencies. | |
*/ | |
var net = require('net'); | |
var tls = require('tls'); | |
var url = require('url'); | |
var Agent = require('./agent'); | |
var inherits = require('util').inherits; | |
/** | |
* Module exports. | |
*/ | |
module.exports = HttpProxyAgent; | |
/** | |
* The `HttpProxyAgent` implements an HTTP Agent subclass that connects to the | |
* specified "HTTP proxy server" in order to proxy HTTP requests. | |
* | |
* @api public | |
*/ | |
function HttpProxyAgent (opts) { | |
if (!(this instanceof HttpProxyAgent)) return new HttpProxyAgent(opts); | |
if ('string' == typeof opts) opts = url.parse(opts); | |
Agent.call(this); | |
this.proxy = opts; | |
this.secure = this.proxy.protocol && this.proxy.protocol == 'https:'; | |
} | |
inherits(HttpProxyAgent, Agent); | |
/** | |
* Called when the node-core HTTP client library is creating a new HTTP request. | |
* | |
* @api public | |
*/ | |
HttpProxyAgent.prototype.addRequest = function (req, host, port, localAddress) { | |
var opts; | |
if ('object' == typeof host) { | |
// >= v0.11.x API | |
opts = host; | |
} else { | |
// <= v0.10.x API | |
opts = { | |
host: host, | |
port: port, | |
localAddress: localAddress | |
}; | |
} | |
// change the `http.ClientRequest` instance's "path" field | |
// to the absolute path of the URL that will be requested | |
var absolute = url.format({ | |
protocol: 'http:', | |
hostname: opts.hostname || opts.host, | |
port: opts.port, | |
pathname: req.path | |
}); | |
req.path = absolute; | |
Agent.prototype.addRequest.apply(this, arguments); | |
}; | |
/** | |
* Initiates a TCP connection to the specified HTTP proxy server. | |
* | |
* @api public | |
*/ | |
HttpProxyAgent.prototype.createConnection = function (opts, fn) { | |
var socket; | |
var info = { | |
host: this.proxy.hostname || this.proxy.host, | |
port: +this.proxy.port || (this.secure ? 443 : 80) | |
}; | |
if (this.secure) { | |
socket = tls.connect(info); | |
} else { | |
socket = net.connect(info); | |
} | |
fn(null, socket); | |
return socket; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Module dependencies. | |
*/ | |
var net = require('net'); | |
var tls = require('tls'); | |
var url = require('url'); | |
var Agent = require('./agent'); | |
var inherits = require('util').inherits; | |
/** | |
* Module exports. | |
*/ | |
module.exports = HttpsProxyAgent; | |
/** | |
* The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to the | |
* specified "HTTP(s) proxy server" in order to proxy HTTPS requests. | |
* | |
* @api public | |
*/ | |
function HttpsProxyAgent (opts) { | |
if (!(this instanceof HttpsProxyAgent)) return new HttpsProxyAgent(opts); | |
if ('string' == typeof opts) opts = url.parse(opts); | |
Agent.call(this); | |
this.proxy = opts; | |
this.secure = this.proxy.protocol && this.proxy.protocol == 'https:'; | |
} | |
inherits(HttpsProxyAgent, Agent); | |
/** | |
* Default port to connect to. | |
*/ | |
Agent.prototype.defaultPort = 443; | |
/** | |
* Initiates a TCP connection to the specified HTTP proxy server. | |
* | |
* @api public | |
*/ | |
HttpsProxyAgent.prototype.createConnection = function (opts, fn) { | |
var socket; | |
var info = { | |
host: this.proxy.hostname || this.proxy.host, | |
port: +this.proxy.port || (this.secure ? 443 : 80) | |
}; | |
if (this.secure) { | |
socket = tls.connect(info); | |
} else { | |
socket = net.connect(info); | |
} | |
var msg = 'CONNECT ' + opts.host + ':' + opts.port + ' HTTP/1.1\r\n' + | |
'Host: ' + opts.host + ':' + opts.port + '\r\n' + | |
'\r\n'; | |
socket.write(msg); | |
socket.ondata = function (b, offset, length) { | |
var buf = b.slice(offset, length); | |
// TODO: verify that the socket is properly connected, check response... | |
socket.ondata = null; | |
// since the proxy is connecting to an SSL server, we have | |
// to upgrade this socket connection to an SSL connection | |
socket = tls.connect({ | |
socket: socket, | |
servername: opts.host | |
}); | |
fn(null, socket); | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Usage example of the `Agent` base class. | |
*/ | |
var url = require('url'); | |
var http = require('http'); | |
var Agent = require('./agent'); | |
var endpoint = process.argv[2] || 'http://nodejs.org/api/'; | |
var opts = url.parse(endpoint); | |
opts.agent = new Agent(); | |
var req = http.get(opts, function (res) { | |
console.log('"response" event!', res.headers); | |
res.pipe(process.stdout); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Usage example of the `HttpProxyAgent` class proxying an HTTP endpoint. | |
*/ | |
var url = require('url'); | |
var http = require('http'); | |
var HttpProxyAgent = require('./http-proxy-agent'); | |
// HTTP proxy to connect to | |
var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; | |
console.log('using proxy server %j', proxy); | |
proxy = url.parse(proxy); | |
// HTTP endpoint for the proxy to connect to | |
var endpoint = process.argv[2] || 'http://nodejs.org/api/'; | |
console.log('attempting to GET %j', endpoint); | |
var opts = url.parse(endpoint); | |
// create an instance of the `HttpProxyAgent` class with the proxy server information | |
var agent = new HttpProxyAgent(proxy); | |
opts.agent = agent; | |
http.get(opts, function (res) { | |
console.log('"response" event!', res.headers); | |
res.pipe(process.stdout); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Usage example of the `HttpsProxyAgent` class proxying an | |
* HTTPS (SSL) endpoint over an HTTP(s) proxy. | |
*/ | |
var url = require('url'); | |
var https = require('https'); | |
var HttpsProxyAgent = require('./https-proxy-agent'); | |
// HTTP proxy to connect to | |
var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; | |
console.log('using proxy server %j', proxy); | |
proxy = url.parse(proxy); | |
// HTTPS endpoint for the proxy to connect to | |
var endpoint = process.argv[2] || 'https://gist.github.com/TooTallNate/5952254/raw/07972db49b5b70a212c39dfee56ed3ab82f8179c/agent.js'; | |
console.log('attempting to GET %j', endpoint); | |
var opts = url.parse(endpoint); | |
// create an instance of the `HttpsProxyAgent` class with the proxy server information | |
opts.agent = new HttpsProxyAgent(proxy); | |
https.get(opts, function (res) { | |
console.log('"response" event!', res.headers); | |
res.pipe(process.stdout); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment