Browse Source

http: Add agent.get/request methods

isaacs 12 years ago
parent
commit
40e92650bb
  1. 41
      lib/_http_agent.js
  2. 28
      lib/http.js
  3. 3
      lib/https.js
  4. 2
      lib/net.js
  5. 91
      test/simple/test-http-keepalive-request.js

41
lib/_http_agent.js

@ -20,8 +20,10 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var net = require('net');
var url = require('url');
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var ClientRequest = require('_http_client').ClientRequest;
// New Agent code.
@ -42,7 +44,9 @@ function Agent(options) {
EventEmitter.call(this);
var self = this;
self.options = options || {};
self.options = util._extend({}, options);
// don't confuse net and make it think that we're connecting to a pipe
self.options.path = null;
self.requests = {};
self.sockets = {};
self.freeSockets = {};
@ -91,7 +95,6 @@ function Agent(options) {
}
}
});
self.createConnection = net.createConnection;
}
util.inherits(Agent, EventEmitter);
@ -99,7 +102,9 @@ exports.Agent = Agent;
Agent.defaultMaxSockets = Infinity;
Agent.prototype.createConnection = net.createConnection;
Agent.prototype.defaultPort = 80;
Agent.prototype.protocol = 'http:';
Agent.prototype.addRequest = function(req, host, port, localAddress) {
var name = host + ':' + port;
if (localAddress) {
@ -207,5 +212,33 @@ Agent.prototype.destroy = function() {
});
};
var globalAgent = new Agent();
exports.globalAgent = globalAgent;
Agent.prototype.request = function(options, cb) {
if (typeof options === 'string') {
options = url.parse(options);
}
if (options && options.path && / /.test(options.path)) {
// The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
// with an additional rule for ignoring percentage-escaped characters
// but that's a) hard to capture in a regular expression that performs
// well, and b) possibly too restrictive for real-world usage. That's
// why it only scans for spaces because those are guaranteed to create
// an invalid request.
throw new TypeError('Request path contains unescaped characters.');
} else if (options.protocol && options.protocol !== this.protocol) {
throw new Error('Protocol:' + options.protocol + ' not supported.');
}
options = util._extend({ agent: this, keepAlive: false }, options);
if (options.agent === false)
options.agent = new Agent(options);
return new ClientRequest(options, cb);
};
Agent.prototype.get = function(options, cb) {
var req = this.request(options, cb);
req.end();
return req;
};

28
lib/http.js

@ -20,7 +20,6 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var util = require('util');
var url = require('url');
var EventEmitter = require('events').EventEmitter;
@ -42,40 +41,21 @@ exports.STATUS_CODES = server.STATUS_CODES;
var agent = require('_http_agent');
var Agent = exports.Agent = agent.Agent;
var globalAgent = exports.globalAgent = agent.globalAgent;
var globalAgent = new Agent();
exports.globalAgent = globalAgent;
var client = require('_http_client');
var ClientRequest = exports.ClientRequest = client.ClientRequest;
exports.request = function(options, cb) {
if (typeof options === 'string') {
options = url.parse(options);
} else if (options && options.path && / /.test(options.path)) {
// The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
// with an additional rule for ignoring percentage-escaped characters
// but that's a) hard to capture in a regular expression that performs
// well, and b) possibly too restrictive for real-world usage. That's
// why it only scans for spaces because those are guaranteed to create
// an invalid request.
throw new TypeError('Request path contains unescaped characters.');
}
if (options.protocol && options.protocol !== 'http:') {
throw new Error('Protocol:' + options.protocol + ' not supported.');
}
return new ClientRequest(options, cb);
return globalAgent.request(options, cb);
};
exports.get = function(options, cb) {
var req = exports.request(options, cb);
req.end();
return req;
return globalAgent.get(options, cb);
};
var httpSocketSetup = common.httpSocketSetup;
exports._connectionListener = server._connectionListener;

3
lib/https.js

@ -83,10 +83,11 @@ function createConnection(port, host, options) {
function Agent(options) {
http.Agent.call(this, options);
this.createConnection = createConnection;
}
inherits(Agent, http.Agent);
Agent.prototype.defaultPort = 443;
Agent.prototype.protocol = 'https:';
Agent.prototype.createConnection = createConnection;
var globalAgent = new Agent();

2
lib/net.js

@ -77,6 +77,7 @@ exports.createServer = function() {
//
exports.connect = exports.createConnection = function() {
var args = normalizeConnectArgs(arguments);
debug('createConnection', args);
var s = new Socket(args[0]);
return Socket.prototype.connect.apply(s, args);
};
@ -832,6 +833,7 @@ Socket.prototype.connect = function(options, cb) {
var self = this;
var pipe = !!options.path;
debug('pipe', pipe, options.path);
if (!this._handle) {
this._handle = pipe ? createPipe() : createTCP();

91
test/simple/test-http-keepalive-request.js

@ -0,0 +1,91 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var common = require('../common');
var assert = require('assert');
var http = require('http');
var serverSocket = null;
var server = http.createServer(function(req, res) {
// They should all come in on the same server socket.
if (serverSocket) {
assert.equal(req.socket, serverSocket);
} else {
serverSocket = req.socket;
}
res.end(req.url);
});
server.listen(common.PORT);
var agent = http.Agent({ keepAlive: true });
var clientSocket = null;
var expectRequests = 10;
var actualRequests = 0;
makeRequest(expectRequests);
function makeRequest(n) {
if (n === 0) {
server.close();
agent.destroy();
return;
}
var req = agent.request({
port: common.PORT,
path: '/' + n
});
req.end();
req.on('socket', function(sock) {
if (clientSocket) {
assert.equal(sock, clientSocket);
} else {
clientSocket = sock;
}
});
req.on('response', function(res) {
var data = '';
res.setEncoding('utf8');
res.on('data', function(c) {
data += c;
});
res.on('end', function() {
assert.equal(data, '/' + n);
setTimeout(function() {
actualRequests++;
makeRequest(n - 1);
}, 1);
});
});
}
process.on('exit', function() {
assert.equal(actualRequests, expectRequests)
console.log('ok');
});
Loading…
Cancel
Save