Skip to content

Commit bd13da4

Browse files
committed
cherry-pick(#32155): fix(client-certificates): when server does tls renegotiation
Certain https servers like Microsoft IIS aka. TLS servers do the TLS renegotiation after the TLS handshake. This ends up in two `'secureConnect'` events due to an upstream Node.js bug: nodejs/node#54362 Drive-by: Move other listeners like `'close'` / `'end'` to `once()` as well. Relates #32004
1 parent 30684a7 commit bd13da4

File tree

1 file changed

+12
-12
lines changed

1 file changed

+12
-12
lines changed

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class ALPNCache {
6060
ALPNProtocols: ['h2', 'http/1.1'],
6161
rejectUnauthorized: false,
6262
}).then(socket => {
63-
socket.on('secureConnect', () => {
63+
socket.once('secureConnect', () => {
6464
// The server may not respond with ALPN, in which case we default to http/1.1.
6565
result.resolve(socket.alpnProtocol || 'http/1.1');
6666
socket.end();
@@ -93,8 +93,8 @@ class SocksProxyConnection {
9393

9494
async connect() {
9595
this.target = await createSocket(rewriteToLocalhostIfNeeded(this.host), this.port);
96-
this.target.on('close', this._targetCloseEventListener);
97-
this.target.on('error', error => this.socksProxy._socksProxy.sendSocketError({ uid: this.uid, error: error.message }));
96+
this.target.once('close', this._targetCloseEventListener);
97+
this.target.once('error', error => this.socksProxy._socksProxy.sendSocketError({ uid: this.uid, error: error.message }));
9898
this.socksProxy._socksProxy.socketConnected({
9999
uid: this.uid,
100100
host: this.target.localAddress!,
@@ -138,9 +138,9 @@ class SocksProxyConnection {
138138
...dummyServerTlsOptions,
139139
ALPNProtocols: alpnProtocolChosenByServer === 'h2' ? ['h2', 'http/1.1'] : ['http/1.1'],
140140
});
141-
this.internal?.on('close', () => dummyServer.close());
141+
this.internal?.once('close', () => dummyServer.close());
142142
dummyServer.emit('connection', this.internal);
143-
dummyServer.on('secureConnection', internalTLS => {
143+
dummyServer.once('secureConnection', internalTLS => {
144144
debugLogger.log('client-certificates', `Browser->Proxy ${this.host}:${this.port} chooses ALPN ${internalTLS.alpnProtocol}`);
145145

146146
let targetTLS: tls.TLSSocket | undefined = undefined;
@@ -162,7 +162,7 @@ class SocksProxyConnection {
162162
this.target.removeListener('close', this._targetCloseEventListener);
163163
// @ts-expect-error
164164
const session: http2.ServerHttp2Session = http2.performServerHandshake(internalTLS);
165-
session.on('stream', (stream: http2.ServerHttp2Stream) => {
165+
session.once('stream', (stream: http2.ServerHttp2Stream) => {
166166
stream.respond({
167167
'content-type': 'text/html',
168168
[http2.constants.HTTP2_HEADER_STATUS]: 503,
@@ -171,7 +171,7 @@ class SocksProxyConnection {
171171
session.close();
172172
closeBothSockets();
173173
});
174-
stream.on('error', () => closeBothSockets());
174+
stream.once('error', () => closeBothSockets());
175175
});
176176
} else {
177177
closeBothSockets();
@@ -208,16 +208,16 @@ class SocksProxyConnection {
208208

209209
targetTLS = tls.connect(tlsOptions);
210210

211-
targetTLS.on('secureConnect', () => {
211+
targetTLS.once('secureConnect', () => {
212212
internalTLS.pipe(targetTLS);
213213
targetTLS.pipe(internalTLS);
214214
});
215215

216-
internalTLS.on('end', () => closeBothSockets());
217-
targetTLS.on('end', () => closeBothSockets());
216+
internalTLS.once('end', () => closeBothSockets());
217+
targetTLS.once('end', () => closeBothSockets());
218218

219-
internalTLS.on('error', () => closeBothSockets());
220-
targetTLS.on('error', handleError);
219+
internalTLS.once('error', () => closeBothSockets());
220+
targetTLS.once('error', handleError);
221221
});
222222
});
223223
}

0 commit comments

Comments
 (0)