Skip to content

Commit

Permalink
Moved to the new 0.4 request API
Browse files Browse the repository at this point in the history
  • Loading branch information
chriso committed Mar 6, 2011
1 parent 3c4e107 commit 01024cc
Showing 1 changed file with 85 additions and 61 deletions.
146 changes: 85 additions & 61 deletions lib/node.io/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

var http = require('http'),
https = require('https'),
resolve = require('url').resolve,
urlparse = require('url').parse,
query = require('querystring'),
Expand Down Expand Up @@ -170,13 +171,15 @@ Job.prototype.encodeBody = function (body, use_json) {
* @api public
*/
Job.prototype.doRequest = function (method, resource, body, headers, callback, parse, redirects) {
var self = this, rid = Math.floor(Math.random() * 100000);
var self = this, port, url, path, rid, secure, request, cleanup, h, request_response, options;

//Give each a request a unique ID for debugging
rid = Math.floor(Math.random() * 100000);

//Internally keep track of the # of redirects
redirects = redirects || 0;
if (redirects > this.options.redirects) {
callback('redirects');
//self.fail_with('redirects');
return;
}

Expand All @@ -195,22 +198,43 @@ Job.prototype.doRequest = function (method, resource, body, headers, callback, p
utils.put_default(headers, default_headers);
}

//Add a protocol if there isn't one
if (!resource.match(/https?:\/\//)) {
resource = 'http://' + resource;
}

var url = urlparse(resource, false), port = url.port;
//Parse the URL into parts
url = urlparse(resource, false),

//Determine the port
port = url.port;
if (!port) {
port = (url.protocol === 'http:') ? 80 : 443;
switch (url.protocol) {
case 'http:':
port = 80;
break;
case 'https:':
port = 443;
secure = true;
break;
case 'ftp:':
port = 21;
break;
default:
port = 80;
}
}

var host = http.createClient(port, url.hostname),
req_url = url.pathname || '/';
//Get the request path
path = url.pathname || '/';
if (url.search) {
path += url.search;
}

//Copy `headers` before modifying it
headers = utils.put({}, headers);

//Set the host header to the URL host unless it's already defined
if (typeof headers.host === 'undefined') {
headers.host = url.hostname;
}
Expand All @@ -225,70 +249,40 @@ Job.prototype.doRequest = function (method, resource, body, headers, callback, p
utils.put(headers, this.next);
this.next = {};

//Set a random user agent if using --spoof
if (this.options.spoof) {
headers['user-agent'] = user_agents[Math.floor(Math.random() * user_agents.length)];
}

if (url.search) {
req_url += url.search;
}

if (typeof body === 'object') {
body = query.stringify(body);
}

//Prepare the body to write and get the content length
if (body) {
if (typeof body === 'object') {
body = query.stringify(body);
}
headers['Content-Length'] = body.length;
}

method = method.toUpperCase();

var request = host.request(method, req_url, headers);

//Debug request headers
this.debug('\033[7m'+method+'\033[0m '+resource + ' (request ' + rid + ')');

this.debug(' | ' + method + ' ' + req_url + ' HTTP/1.1');
for (var h in headers) {
this.debug(' | ' + method + ' ' + path + ' HTTP/1.1');
for (h in headers) {
this.debug(' | ' + h[0].toUpperCase() + h.substr(1) + ': ' + headers[h]);
}

if (body) {
request.write(body);
}

//This method is called on each event if the instance is already complete (i.e. timed out)
var cleanup = function () {
if (request) {
if (request.socket && request.socket.destroy) {
request.socket.destroy();
}
}
if (host.destroy) {
host.destroy();
}
options = {
host: headers.host,
port: port,
path: path,
method: method,
headers: headers
};

//Watch for errors
host.addListener('error', function (connectionException) {
if (self.is_complete) return;
self.debug('Request ' + rid + ' failed with: ('+connectionException.errno+') ' + connectionException + ' ('+resource+')');
callback(connectionException);
cleanup();
});
request = (secure ? https : http).request(options, function (response) {

//Set a special timeout if the `timeout` option is set. Redirects do not reset the timeout
if (this.options.timeout && redirects === 0) {
self.cancel_timeout();
self.timeout = setTimeout(function() {
if (self.is_complete) return;
self.debug('Request ' + rid + ' timed out ('+resource+')');
//self.fail_with('timeout');
callback('timeout');
cleanup();
}, this.options.timeout * 1000);
}
request_reponse = response;

request.on('response', function (response) {
if (self.is_complete) {
return cleanup();
}
Expand All @@ -297,8 +291,8 @@ Job.prototype.doRequest = function (method, resource, body, headers, callback, p

var code = response.statusCode || 200;

//Debug response headers
self.debug('\033[7m'+code+'\033[0m '+resource + ' (response ' + rid + ')');

for (h in response.headers) {
self.debug(' | ' + h[0].toUpperCase() + h.substr(1) + ': ' + response.headers[h]);
}
Expand All @@ -316,14 +310,12 @@ Job.prototype.doRequest = function (method, resource, body, headers, callback, p
switch (Math.floor(code/100)) {
case 4:
case 5:
callback(code);
return;

return callback(code);
case 3:
if (typeof response.headers.location === 'undefined') {
callback(code);
} else {
//self.debug(' \033[7m>\033[0m ' + response.headers.location);
//Handle the 30x redirect
var location = resolve(resource, response.headers.location);
self.doRequest(method, location, body, headers, callback, parse, ++redirects);
}
Expand Down Expand Up @@ -363,13 +355,45 @@ Job.prototype.doRequest = function (method, resource, body, headers, callback, p

cleanup();
});

});

if (request.end) {
request.end();
} else {
request.close();
//Write a body if it was specified
if (body) {
request.write(body);
}

//This method is called on each event if the instance is already complete (i.e. timed out)
cleanup = function () {
if (request.socket && request.socket.destroy) {
request.socket.destroy();
}
if (request_response) {
request_response.abort();
}
};

//Watch for errors
request.on('error', function (err) {
if (self.is_complete) return;
self.debug('Request ' + rid + ' failed with: (' + err.errno + ') ' + err + ' ('+resource+')');
cleanup();
callback(err);
});

//Set a special timeout if the `timeout` option is set. Redirects do not reset the timeout
if (this.options.timeout && redirects === 0) {
self.cancel_timeout();
self.timeout = setTimeout(function() {
if (self.is_complete) return;
self.debug('Request ' + rid + ' timed out ('+resource+')');
cleanup();
callback('timeout');
}, this.options.timeout * 1000);
}

//We're done
request.end();
};

/**
Expand Down

0 comments on commit 01024cc

Please sign in to comment.