Skip to content

Commit ac05145

Browse files
authored
fix(fetch): report serverAddr and securityDetails for reused sockets (#41267)
1 parent 056efc9 commit ac05145

2 files changed

Lines changed: 32 additions & 20 deletions

File tree

packages/playwright-core/src/server/fetch.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ import { isAbortError } from './progress';
3737
import { getMatchingTLSOptionsForOrigin, rewriteOpenSSLErrorIfNeeded } from './socksClientCertificatesInterceptor';
3838
import { Tracing } from './trace/recorder/tracing';
3939

40+
import type net from 'net';
41+
4042
import type { Playwright } from './playwright';
4143
import type { Progress } from './progress';
4244
import type * as types from './types';
@@ -552,9 +554,26 @@ export abstract class APIRequestContext extends SdkObject {
552554
);
553555
request.on('close', () => eventsHelper.removeEventListeners(listeners));
554556

557+
const captureSecurityDetails = (socket: net.Socket) => {
558+
if (!(socket instanceof TLSSocket))
559+
return;
560+
const peerCertificate = socket.getPeerCertificate();
561+
securityDetails = {
562+
protocol: socket.getProtocol() ?? undefined,
563+
subjectName: peerCertificate.subject.CN,
564+
validFrom: new Date(peerCertificate.valid_from).getTime() / 1000,
565+
validTo: new Date(peerCertificate.valid_to).getTime() / 1000,
566+
issuer: peerCertificate.issuer.CN
567+
};
568+
};
569+
555570
request.on('socket', socket => {
571+
serverIPAddress = socket.remoteAddress;
572+
serverPort = socket.remotePort;
573+
556574
if (request.reusedSocket) {
557575
reusedSocketAt = monotonicTime();
576+
captureSecurityDetails(socket);
558577
return;
559578
}
560579

@@ -569,22 +588,9 @@ export abstract class APIRequestContext extends SdkObject {
569588
eventsHelper.addEventListener(socket, 'connect', () => { tcpConnectionAt = monotonicTime(); }),
570589
eventsHelper.addEventListener(socket, 'secureConnect', () => {
571590
tlsHandshakeAt = monotonicTime();
572-
573-
if (socket instanceof TLSSocket) {
574-
const peerCertificate = socket.getPeerCertificate();
575-
securityDetails = {
576-
protocol: socket.getProtocol() ?? undefined,
577-
subjectName: peerCertificate.subject.CN,
578-
validFrom: new Date(peerCertificate.valid_from).getTime() / 1000,
579-
validTo: new Date(peerCertificate.valid_to).getTime() / 1000,
580-
issuer: peerCertificate.issuer.CN
581-
};
582-
}
591+
captureSecurityDetails(socket);
583592
}),
584593
);
585-
586-
serverIPAddress = socket.remoteAddress;
587-
serverPort = socket.remotePort;
588594
});
589595
request.on('finish', () => { requestFinishAt = monotonicTime(); });
590596

tests/library/global-fetch.spec.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,17 +236,23 @@ it('should propagate ignoreHTTPSErrors on redirects', async ({ playwright, https
236236

237237
it('should return server address from response', async ({ playwright, server }) => {
238238
const request = await playwright.request.newContext();
239-
const response = await request.get(server.EMPTY_PAGE);
240-
const addr = await response.serverAddr();
241-
expect(addr!.ipAddress).toMatch(/^(127\.0\.0\.1|::1)$/);
242-
expect(addr!.port).toBe(server.PORT);
239+
// The second request reuses the keep-alive socket and should report the address as well.
240+
for (let i = 0; i < 2; i++) {
241+
const response = await request.get(server.EMPTY_PAGE);
242+
const addr = await response.serverAddr();
243+
expect(addr!.ipAddress).toMatch(/^(127\.0\.0\.1|::1)$/);
244+
expect(addr!.port).toBe(server.PORT);
245+
}
243246
await request.dispose();
244247
});
245248

246249
it('should return security details from response', async ({ playwright, httpsServer }) => {
247250
const request = await playwright.request.newContext({ ignoreHTTPSErrors: true });
248-
const response = await request.get(httpsServer.EMPTY_PAGE);
249-
expect(await response.securityDetails()).toEqual({ issuer: 'playwright-test', protocol: 'TLSv1.3', subjectName: 'playwright-test', validFrom: 1691708270, validTo: 2007068270 });
251+
// The second request reuses the keep-alive socket and should report the details as well.
252+
for (let i = 0; i < 2; i++) {
253+
const response = await request.get(httpsServer.EMPTY_PAGE);
254+
expect(await response.securityDetails()).toEqual({ issuer: 'playwright-test', protocol: 'TLSv1.3', subjectName: 'playwright-test', validFrom: 1691708270, validTo: 2007068270 });
255+
}
250256
await request.dispose();
251257
});
252258

0 commit comments

Comments
 (0)