Skip to content

Commit

Permalink
Added timing tests for http2
Browse files Browse the repository at this point in the history
  • Loading branch information
parthverma1 committed Jun 14, 2024
1 parent ed1db1d commit 3cacefe
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 21 deletions.
2 changes: 1 addition & 1 deletion request.js
Original file line number Diff line number Diff line change
Expand Up @@ -1233,7 +1233,7 @@ Request.prototype.onRequestResponse = function (response) {
if (!self.timings.connect) {
self.timings.connect = self.timings.lookup
}
if (!self.timings.secureConnect && self.httpModule === https) {
if (!self.timings.secureConnect && self.uri.protocol === 'https:') {
self.timings.secureConnect = self.timings.connect
}
if (!self.timings.response) {
Expand Down
35 changes: 15 additions & 20 deletions tests/test-brotli-http2.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,14 @@ function requestHandler (req, res) {
res.stream.on('close', () => {
session.close()
})
// res.on('finish', () => {
// console.log('finish');
// session.close();
// });

if (/\bbr\b/i.test(req.headers['accept-encoding'])) {
res.setHeader('Content-Encoding', 'br')
if (req.url === '/error') {
res.writeHead(200)
// send plaintext instead of br (should cause an error for the client)
res.end(testContent)
} else if (req.url === '/chunks') {
console.log('chunks')
res.writeHead(200)
res.write(Buffer.from(testContentBigBrotli.slice(0, 4096)))
setTimeout(function () {
Expand Down Expand Up @@ -83,7 +79,7 @@ tape('setup', function (t) {

s.on('/foo', requestHandler)
s.on('/error', requestHandler)
s.on('/chunk', requestHandler)
s.on('/chunks', requestHandler)
s.listen(0, function () {
t.end()
})
Expand All @@ -93,7 +89,6 @@ tape('transparently supports brotli decoding to callbacks', function (t) {
var options = {
url: s.url + '/foo',
brotli: true,

protocolVersion: 'h2',
strictSSL: false
}
Expand Down Expand Up @@ -242,19 +237,19 @@ tape('transparently supports brotli error to pipes', function (t) {
})
})

// tape("pause when streaming from a brotli request object", {todo: true}, function (t) {
// var options = {
// url: s.url + "/chunks",
// brotli: true,
// protocolVersion: "h2",
// strictSSL: false,
// };
// request.get(options, function (err, res, body) {
// t.equal(err, null);
// t.equal(body, testContentBig.toString());
// t.end();
// });
// });
tape("pause when streaming from a brotli request object", function (t) {
var options = {
url: s.url + "/chunks",
brotli: true,
protocolVersion: "h2",
strictSSL: false,
};
request.get(options, function (err, res, body) {
t.equal(err, null);
t.equal(body, testContentBig.toString());
t.end();
});
});

tape('pause before streaming from a brotli request object', function (t) {
var paused = true
Expand Down
176 changes: 176 additions & 0 deletions tests/test-timing-http2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
'use strict'

var tape = require('tape')
var destroyable = require('server-destroy')

var server = require('./server')
var request = require('../index')

var plainServer = server.createServer()
var httpsServer = server.createHttp2Server()
var redirectMockTime = 10

destroyable(plainServer)
destroyable(httpsServer);

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

httpsServer.listen(0, function () {
httpsServer.on('/', function (req, res) {
res.writeHead(200)
res.end('https')
})
httpsServer.on('/redir', function (req, res) {
// fake redirect delay to ensure strong signal for rollup check
setTimeout(function () {
res.writeHead(301, { 'location': 'https://localhost:' + httpsServer.port + '/' })
res.end()
}, redirectMockTime)
})

t.end()
})
})
})

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


tape('HTTPS: non-redirected request is timed', function (t) {
var options = {time: true, strictSSL: false, protocolVersion: 'h2'}

var start = new Date().getTime()
var r = request('https://localhost:' + httpsServer.port + '/', options, function (err, res, body) {
var end = new Date().getTime()

t.equal(err, null)
t.equal(typeof res.elapsedTime, 'number')
t.equal(typeof res.responseStartTime, 'number')
t.equal(typeof res.timingStartTimer, 'number')
t.equal(typeof res.timingStart, 'number')
t.equal((res.timingStart >= start), true)
t.equal(typeof res.timings, 'object')
t.equal((res.elapsedTime > 0), true)
t.equal((res.elapsedTime <= (end - start)), true)
t.equal((res.responseStartTime > r.startTime), true)
t.equal((res.timings.socket >= 0), true)
t.equal((res.timings.lookup >= res.timings.socket), true)
t.equal((res.timings.connect >= res.timings.lookup), true)
t.equal((res.timings.secureConnect >= res.timings.connect), true)
t.equal((res.timings.response >= res.timings.secureConnect), true)
t.equal((res.timings.end >= res.timings.response), true)
t.equal(typeof res.timingPhases, 'object')
t.equal((res.timingPhases.wait >= 0), true)
t.equal((res.timingPhases.dns >= 0), true)
t.equal((res.timingPhases.tcp >= 0), true)
t.equal((res.timingPhases.secureHandshake >= 0), true)
t.equal((res.timingPhases.firstByte > 0), true)
t.equal((res.timingPhases.download > 0), true)
t.equal((res.timingPhases.total > 0), true)
t.equal((res.timingPhases.total <= (end - start)), true)

// validate there are no unexpected properties
var propNames = []
for (var propName in res.timings) {
if (res.timings.hasOwnProperty(propName)) {
propNames.push(propName)
}
}
t.deepEqual(propNames, ['socket', 'lookup', 'connect', 'secureConnect', 'response', 'end'])

propNames = []
for (propName in res.timingPhases) {
if (res.timingPhases.hasOwnProperty(propName)) {
propNames.push(propName)
}
}
t.deepEqual(propNames, ['wait', 'dns', 'tcp', 'firstByte', 'download', 'total', 'secureHandshake'])

t.end()
})
})

tape('HTTPS: redirected request is timed with rollup', function (t) {
var options = {time: true, strictSSL: false}
var r = request('https://localhost:' + httpsServer.port + '/redir', options, function (err, res, body) {
t.equal(err, null)
t.equal(typeof res.elapsedTime, 'number')
t.equal(typeof res.responseStartTime, 'number')
t.equal((res.elapsedTime > 0), true)
t.equal((res.responseStartTime > 0), true)
t.equal((res.elapsedTime > redirectMockTime), true)
t.equal((res.responseStartTime > r.startTime), true)
t.end()
})
})

tape('HTTPS/2: Reused stream is timed', function (t) {
var options = { time: true, strictSSL: false }
var start1 = new Date().getTime()

request('https://localhost:' + httpsServer.port + '/', options, function (err1, res1, body1) {
var end1 = new Date().getTime()

t.equal(err1, null)
// ensure the first request's timestamps look ok
t.equal((res1.timingStart >= start1), true)
t.equal((start1 <= end1), true)

t.equal((res1.timings.socket >= 0), true)
t.equal((res1.timings.lookup >= res1.timings.socket), true)
t.equal((res1.timings.connect >= res1.timings.lookup), true)
t.equal((res1.timings.secureConnect >= res1.timings.connect), true)
t.equal((res1.timings.response >= res1.timings.secureConnect), true)

// open a second request with the same agent so we re-use the same connection
var start2 = new Date().getTime()

request('https://localhost:' + httpsServer.port + '/', options, function (err2, res2, body2) {
var end2 = new Date().getTime()

// ensure the second request's timestamps look ok
t.equal((res2.timingStart >= start2), true)
t.equal((start2 <= end2), true)

// ensure socket==lookup==connect==secureConnect for the second request
t.equal((res2.timings.socket >= 0), true)
t.equal((res2.timings.lookup === res2.timings.socket), true)
t.equal((res2.timings.connect === res2.timings.lookup), true)
t.equal((res2.timings.secureConnect === res2.timings.connect), true)
t.equal((res2.timings.response >= res2.timings.connect), true)
t.end()
})
})
})

tape('cleanup', function (t) {
plainServer.destroy(function () {
httpsServer.destroy(function () {
t.end()
})
})
})

0 comments on commit 3cacefe

Please sign in to comment.