Skip to content

Commit

Permalink
feat: secureConnect timeout for https requests
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan Stewmon committed Jul 25, 2018
1 parent 344cb3f commit 6643f8c
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 3 deletions.
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ This also accepts an object with separate `lookup`, `connect`, `socket`, `respon

- `lookup` starts when a socket is assigned and ends when the hostname has been resolved. Does not apply when using a Unix domain socket.
- `connect` starts when `lookup` completes (or when the socket is assigned if lookup does not apply to the request) and ends when the socket is connected.
- `secureConnect` starts when `connect` completes and ends when the handshaking process completes (https only).
- `socket` starts when the socket is connected. See [request.setTimeout](https://nodejs.org/api/http.html#http_request_settimeout_timeout_callback).
- `response` starts when the request has been written to the socket and ends when the response headers are received.
- `send` starts when the socket is connected and ends with the request has been written to the socket.
Expand Down
16 changes: 16 additions & 0 deletions source/timed-out.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,22 @@ module.exports = (request, options) => {
});
}

if (delays.secureConnect !== undefined && options.protocol === 'https:') {
request.once('socket', socket => {
if (socket.connecting) {
socket.once('connect', () => {
const cancelTimeout = addTimeout(
delays.secureConnect,
timeoutHandler,
'secureConnect'
);
cancelers.push(cancelTimeout);
socket.once('secureConnect', cancelTimeout);
})
}
})
}

if (delays.send !== undefined) {
request.once('socket', socket => {
const timeRequest = () => {
Expand Down
40 changes: 37 additions & 3 deletions test/timeout.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import test from 'ava';
import pEvent from 'p-event';
import delay from 'delay';
import got from '../source';
import {createServer} from './helpers/server';
import {createServer, createSSLServer} from './helpers/server';

let s;
let ss;

const slowDataStream = () => {
const slowStream = new stream.PassThrough();
Expand Down Expand Up @@ -36,7 +37,7 @@ const keepAliveAgent = new http.Agent({
});

test.before('setup', async () => {
s = await createServer();
[s, ss] = await Promise.all([createServer(), createSSLServer()]);

s.on('/', async (request, response) => {
request.on('data', () => {});
Expand All @@ -58,7 +59,11 @@ test.before('setup', async () => {
response.end('OK');
});

await s.listen(s.port);
ss.on('/', async (request, response) => {
response.end('OK');
});

await Promise.all([s.listen(s.port), ss.listen(ss.port)]);
});

test('timeout option (ETIMEDOUT)', async t => {
Expand Down Expand Up @@ -248,6 +253,35 @@ test('connect timeout (ip address)', async t => {
);
});

test('secureConnect timeout', async t => {
await t.throws(
got(ss.url, {
timeout: {secureConnect: 2},
retry: 0,
rejectUnauthorized: false
}),
{
...errorMatcher,
message: `Timeout awaiting 'secureConnect' for 1ms`
}
);
});

test('secureConnect timeout not breached', async t => {
const secureConnect = 200;
await got(ss.url, {
timeout: {secureConnect},
retry: 0,
rejectUnauthorized: false
}).on('request', request => {
request.on('error', error => {
t.fail(`error emitted: ${error}`);
});
});
await delay(secureConnect * 2);
t.pass('no error emitted');
});

test('lookup timeout', async t => {
await t.throws(
got({
Expand Down

0 comments on commit 6643f8c

Please sign in to comment.