Skip to content

Commit

Permalink
global response event. fixed #35
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 committed Aug 25, 2014
1 parent 8248945 commit 7b8c6af
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 10 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,21 @@ co(function* () {
})();
```

## Global `response` event

```js
urllib.on('response', function (info) {
error: err,
url: url,
options: options,
status: statusCode,
rt: requestUsetime,
requestSize: requestSize,
responseSize: responseSize,
headers: headers
});
```

## API Doc

### Method: `http.request(url[, options][, callback])`
Expand Down
81 changes: 71 additions & 10 deletions lib/urllib.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var fs = require('fs');
var zlib = require('zlib');
var ua = require('default-user-agent');
var digestAuthHeader = require('digest-header');
var EventEmitter = require('events').EventEmitter;
var _Promise;

var pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../', 'package.json')));
Expand Down Expand Up @@ -140,6 +141,7 @@ exports.requestWithCallback = function (url, args, callback) {

args.timeout = args.timeout || exports.TIMEOUT;
args.maxRedirects = args.maxRedirects || 10;
var requestStartTime = Date.now();
var parsedUrl = typeof url === 'string' ? urlutil.parse(url) : url;

var method = (args.type || args.method || parsedUrl.method || 'GET').toUpperCase();
Expand Down Expand Up @@ -218,12 +220,13 @@ exports.requestWithCallback = function (url, args, callback) {
body = null;
}

var requestSize = 0;
if (body) {
var length = body.length;
if (!Buffer.isBuffer(body)) {
length = Buffer.byteLength(body);
}
options.headers['Content-Length'] = length;
requestSize = options.headers['Content-Length'] = length;
}

if (args.dataType === 'json') {
Expand Down Expand Up @@ -254,9 +257,17 @@ exports.requestWithCallback = function (url, args, callback) {
}
var cb = callback;
callback = null;
var statusCode = -1;
var headers = {};
var responseSize = 0;
if (res) {
statusCode = res.statusCode;
headers = res.headers;
responseSize = res.size;
}

if (err) {
var statusCode = res && res.statusCode || -1;
var headers = JSON.stringify(res && res.headers || {});
var headers = JSON.stringify(headers);
err.message += ', ' + options.method + ' ' + url + ' ' + statusCode
+ '\nheaders: ' + headers;
if (res) {
Expand All @@ -267,10 +278,11 @@ exports.requestWithCallback = function (url, args, callback) {
};
}
err.data = data;
err.status = statusCode;
}

// handle digest auth
if (res && res.statusCode === 401 && res.headers['www-authenticate']
if (statusCode === 401 && headers['www-authenticate']
&& (!args.headers || !args.headers.Authorization) && args.digestAuth) {
var authenticate = res.headers['www-authenticate'];
if (authenticate.indexOf('Digest ') >= 0) {
Expand All @@ -285,7 +297,23 @@ exports.requestWithCallback = function (url, args, callback) {
}
}

var requestUsetime = Date.now() - requestStartTime;
debug('[%sms] %s bytes HTTP %s %s %s',
requestUsetime, responseSize, statusCode, options.method, options.path);

cb(err, data, res);
if (exports.events) {
exports.events.emit('response', {
error: err,
url: url,
options: options,
status: statusCode,
rt: requestUsetime,
requestSize: requestSize,
responseSize: responseSize,
headers: headers,
});
}
};

var handleRedirect = function (res) {
Expand Down Expand Up @@ -420,6 +448,7 @@ exports.requestWithCallback = function (url, args, callback) {
});

res.on('end', function () {
res.size = size;
var body = Buffer.concat(chunks, size);
debug('Request#%d %s: `res end` event emit, total size %d, _dumped: %s', reqId, url, size, res._dumped);

Expand All @@ -443,13 +472,15 @@ exports.requestWithCallback = function (url, args, callback) {

// if body not decode, dont touch it
if (!encoding && args.dataType === 'json') {
try {
data = size > 0 ? JSON.parse(data) : null;
} catch (e) {
if (e.name === 'SyntaxError') {
e.name = 'JSONResponseFormatError';
if (size === 0) {
data = null;
} else {
var r = parseJSON(data);
if (r.error) {
err = r.error;
} else {
data = r.data;
}
err = e;
}
}

Expand Down Expand Up @@ -521,3 +552,33 @@ exports.requestWithCallback = function (url, args, callback) {
req.requestId = reqId;
return req;
};

function parseJSON(data) {
var result = {
error: null,
data: null
};
try {
result.data = JSON.parse(data);
} catch (e) {
if (e.name === 'SyntaxError') {
e.name = 'JSONResponseFormatError';
}
result.error = e;
}
return result;
}

exports.on = function (event, listener) {
if (!exports.events) {
exports.events = new EventEmitter();
}
exports.events.on(event, listener);
};

exports.removeAllListeners = function (event) {
if (!exports.events) {
return;
}
exports.events.removeAllListeners(event);
};
36 changes: 36 additions & 0 deletions test/urllib.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -931,4 +931,40 @@ describe('urllib.test.js', function () {
});
});
});

describe('on()', function () {
afterEach(function () {
urllib.removeAllListeners('response');
});

it('should listen response event', function (done) {
done = pedding(4, done);
urllib.on('response', function (info) {
if (info.options.path === '/error') {
should.exist(info.error);
info.status.should.equal(-1);
info.requestSize.should.equal(0);
} else {
should.not.exist(info.error);
info.status.should.equal(200);
info.requestSize.should.equal(7);
info.responseSize.should.equal(info.requestSize);
info.options.path.should.equal('/stream');
}
done();
});
urllib.request(host + '/error', function (err) {
should.exist(err);
done();
});

urllib.request(host + '/stream', {
method: 'post',
data: {foo: 'bar'}
}, function (err) {
should.not.exist(err);
done();
});
});
});
});

0 comments on commit 7b8c6af

Please sign in to comment.