Skip to content

Commit

Permalink
Merge pull request #1459 from aaron-em/master
Browse files Browse the repository at this point in the history
Add option to time request/response cycle (including rollup of redirects)
  • Loading branch information
seanstrom committed Mar 13, 2015
2 parents 2377115 + 19f0c51 commit 5e7b73d
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -607,7 +607,7 @@ The first argument can be either a `url` or an `options` object. The only requir
* `hawk` - Options for [Hawk signing](https://github.com/hueniverse/hawk). The `credentials` key must contain the necessary signing info, [see hawk docs for details](https://github.com/hueniverse/hawk#usage-example).
* `strictSSL` - If `true`, requires SSL certificates be valid. **Note:** to use your own certificate authority, you need to specify an agent that was created with that CA as an option.
* `agentOptions` - Object containing user agent options. See documentation above. **Note:** [see tls API doc for TLS/SSL options](http://nodejs.org/api/tls.html#tls_tls_connect_options_callback).
* `time` - If `true`, the request-response cycle (including all redirects) is timed at millisecond resolution, and the result provided on the response's `elapsedTime` property.
* `jar` - If `true` and `tough-cookie` is installed, remember cookies for future use (or define your custom cookie jar; see examples section)
* `aws` - `object` containing AWS signing information. Should have the properties `key`, `secret`. Also requires the property `bucket`, unless you’re specifying your `bucket` as part of the path, or the request doesn’t use a bucket (i.e. GET Services)
* `httpSignature` - Options for the [HTTP Signature Scheme](https://github.com/joyent/node-http-signature/blob/master/http_signing.md) using [Joyent's library](https://github.com/joyent/node-http-signature). The `keyId` and `key` properties must be specified. See the docs for other options.
Expand Down
19 changes: 17 additions & 2 deletions request.js
Expand Up @@ -282,7 +282,7 @@ Request.prototype.setupTunnel = function () {
if (typeof self.proxy === 'string') {
self.proxy = url.parse(self.proxy)
}

if (!self.proxy || !self.tunnel) {
return false
}
Expand All @@ -298,7 +298,7 @@ Request.prototype.setupTunnel = function () {
self.proxyHeaders = constructProxyHeaderWhiteList(self.headers, proxyHeaderWhiteList)
self.proxyHeaders.host = constructProxyHost(self.uri)
proxyHeaderExclusiveList.forEach(self.removeHeader, self)

// Set Agent from Tunnel Data
var tunnelFn = getTunnelFn(self)
var tunnelOptions = constructTunnelOptions(self)
Expand Down Expand Up @@ -550,6 +550,11 @@ Request.prototype.init = function (options) {
self.multipart(options.multipart)
}

if (options.time) {
self.timing = true
self.elapsedTime = self.elapsedTime || 0
}

if (self.body) {
var length = 0
if (!Buffer.isBuffer(self.body)) {
Expand Down Expand Up @@ -893,8 +898,13 @@ Request.prototype.start = function () {
delete reqOptions.auth

debug('make request', self.uri.href)

self.req = self.httpModule.request(reqOptions)

if (self.timing) {
self.startTime = new Date().getTime()
}

if (self.timeout && !self.timeoutTimer) {
var timeout = self.timeout < 0 ? 0 : self.timeout
self.timeoutTimer = setTimeout(function () {
Expand Down Expand Up @@ -958,6 +968,11 @@ Request.prototype.onRequestResponse = function (response) {
var self = this
debug('onRequestResponse', self.uri.href, response.statusCode, response.headers)
response.on('end', function() {
if (self.timing) {
self.elapsedTime += (new Date().getTime() - self.startTime)
debug('elapsed time', self.elapsedTime)
response.elapsedTime = self.elapsedTime
}
debug('response end', self.uri.href, response.statusCode, response.headers)
})

Expand Down
54 changes: 54 additions & 0 deletions tests/test-timing.js
@@ -0,0 +1,54 @@
'use strict'

var http = require('http')
, server = require('./server')
, request = require('../index')
, tape = require('tape')

var plain_server = server.createServer()
, redirect_mock_time = 10

tape('setup', function(t) {
plain_server.listen(plain_server.port, function() {
plain_server.on('/', function (req, res) {
res.writeHead(200)
res.end('plain')
})
plain_server.on('/redir', function (req, res) {
// fake redirect delay to ensure strong signal for rollup check
setTimeout(function() {
res.writeHead(301, { 'location': 'http://localhost:' + plain_server.port + '/' })
res.end()
}, redirect_mock_time)
})

t.end()
})
})

tape('non-redirected request is timed', function(t) {
var options = {time: true}
request('http://localhost:' + plain_server.port + '/', options, function(err, res, body) {
t.equal(err, null)
t.equal(typeof res.elapsedTime, 'number')
t.equal((res.elapsedTime > 0), true)
t.end()
})
})

tape('redirected request is timed with rollup', function(t) {
var options = {time: true}
request('http://localhost:' + plain_server.port + '/redir', options, function(err, res, body) {
t.equal(err, null)
t.equal(typeof res.elapsedTime, 'number')
t.equal((res.elapsedTime > 0), true)
t.equal((res.elapsedTime > redirect_mock_time), true)
t.end()
})
})

tape('cleanup', function(t) {
plain_server.close(function() {
t.end()
})
})

0 comments on commit 5e7b73d

Please sign in to comment.