Skip to content

Commit 3d66aec

Browse files
committed
Fix DNS timing being non-zero when connecting to IP addresses
Fixes #2279
1 parent 0863bcd commit 3d66aec

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

source/core/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,19 @@ export default class Request extends Duplex implements RequestEvents<Request> {
712712
this._responseSize = Number(response.headers['content-length']) || undefined;
713713
this.response = typedResponse;
714714

715+
// Workaround for http-timer bug: when connecting to an IP address (no DNS lookup),
716+
// http-timer sets lookup = connect instead of lookup = socket, resulting in
717+
// dns = lookup - socket being a small positive number instead of 0.
718+
// See https://github.com/sindresorhus/got/issues/2279
719+
const {timings} = response;
720+
if (timings?.lookup !== undefined && timings.socket !== undefined && timings.connect !== undefined && timings.lookup === timings.connect && timings.phases.dns !== 0) {
721+
// Fix the DNS phase to be 0 and set lookup to socket time
722+
timings.phases.dns = 0;
723+
timings.lookup = timings.socket;
724+
// Recalculate TCP time to be the full time from socket to connect
725+
timings.phases.tcp = timings.connect - timings.socket;
726+
}
727+
715728
response.once('error', (error: Error) => {
716729
this._aborted = true;
717730

test/timings.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import test from 'ava';
2+
import got from '../source/index.js';
23
import withServer, {withHttpsServer} from './helpers/with-server.js';
34

45
test('http/1 timings', withServer, async (t, server, got) => {
@@ -85,3 +86,19 @@ test('timings.end is set when stream is destroyed before completion', withServer
8586

8687
t.pass();
8788
});
89+
90+
test('dns timing is 0 for IP addresses', withServer, async (t, server) => {
91+
server.get('/', (_request, response) => {
92+
response.end('ok');
93+
});
94+
95+
// Get the actual IP address the server is bound to
96+
const address = server.http.address() as {address: string; family: string; port: number};
97+
const host = address.family === 'IPv6' ? `[${address.address}]` : address.address;
98+
const {timings} = await got(`http://${host}:${server.port}/`);
99+
100+
// When connecting to an IP address, there is no DNS lookup
101+
t.is(timings.phases.dns, 0);
102+
// Lookup timestamp should equal socket timestamp (no time elapsed for DNS)
103+
t.is(timings.lookup, timings.socket);
104+
});

0 commit comments

Comments
 (0)