1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 04:52:26 -05:00

fix(ext/node): fix playwright http client (#27662)

This commit is contained in:
Yoshiya Hinosawa 2025-01-15 01:00:55 +09:00 committed by GitHub
parent 0b033140c0
commit c943f56949
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 19 additions and 11 deletions

View file

@ -154,7 +154,7 @@ export class TLSSocket extends net.Socket {
const afterConnect = handle.afterConnect; const afterConnect = handle.afterConnect;
handle.afterConnect = async (req: any, status: number) => { handle.afterConnect = async (req: any, status: number) => {
options.hostname ??= undefined; // coerce to undefined if null, startTls expects hostname to be undefined options.hostname ??= undefined; // coerce to undefined if null, startTls expects hostname to be undefined
if (tlssock._isNpmAgent) { if (tlssock._needsSockInitWorkaround) {
// skips the TLS handshake for @npmcli/agent as it's handled by // skips the TLS handshake for @npmcli/agent as it's handled by
// onSocket handler of ClientRequest object. // onSocket handler of ClientRequest object.
tlssock.emit("secure"); tlssock.emit("secure");

View file

@ -1157,6 +1157,13 @@ function _emitCloseNT(s: Socket | Server) {
s.emit("close"); s.emit("close");
} }
// The packages that need socket initialization workaround
const pkgsNeedsSockInitWorkaround = [
"@npmcli/agent",
"npm-check-updates",
"playwright-core",
];
/** /**
* This class is an abstraction of a TCP socket or a streaming `IPC` endpoint * This class is an abstraction of a TCP socket or a streaming `IPC` endpoint
* (uses named pipes on Windows, and Unix domain sockets otherwise). It is also * (uses named pipes on Windows, and Unix domain sockets otherwise). It is also
@ -1201,9 +1208,11 @@ export class Socket extends Duplex {
_host: string | null = null; _host: string | null = null;
// deno-lint-ignore no-explicit-any // deno-lint-ignore no-explicit-any
_parent: any = null; _parent: any = null;
// The flag for detecting if it's called in @npmcli/agent // Skip some initialization (initial read and tls handshake if it's tls socket).
// If this flag is true, it's used as connection for http(s) request, and
// the reading and TLS handshake is done by the http client.
// See discussions in https://github.com/denoland/deno/pull/25470 for more details. // See discussions in https://github.com/denoland/deno/pull/25470 for more details.
_isNpmAgent = false; _needsSockInitWorkaround = false;
autoSelectFamilyAttemptedAddresses: AddressInfo[] | undefined = undefined; autoSelectFamilyAttemptedAddresses: AddressInfo[] | undefined = undefined;
constructor(options: SocketOptions | number) { constructor(options: SocketOptions | number) {
@ -1224,21 +1233,20 @@ export class Socket extends Duplex {
super(options); super(options);
// Note: If the socket is created from one of: // Note: If the socket is created from one of `pkgNeedsSockInitWorkaround`,
// - @npmcli/agent
// - npm-check-updates (bundles @npmcli/agent as a dependency)
// the 'socket' event on ClientRequest object happens after 'connect' event on Socket object. // the 'socket' event on ClientRequest object happens after 'connect' event on Socket object.
// That swaps the sequence of op_node_http_request_with_conn() call and // That swaps the sequence of op_node_http_request_with_conn() call and
// initial socket read. That causes op_node_http_request_with_conn() not // initial socket read. That causes op_node_http_request_with_conn() not
// working. // working.
// To avoid the above situation, we detect the socket created from // To avoid the above situation, we detect the socket created from
// @npmcli/agent and pause the socket (and also skips the startTls call // one of those packages using stack trace and pause the socket
// if it's TLSSocket) // (and also skips the startTls call if it's TLSSocket)
// TODO(kt3k): Remove this workaround // TODO(kt3k): Remove this workaround
const errorStack = new Error().stack; const errorStack = new Error().stack;
this._isNpmAgent = errorStack?.includes("@npmcli/agent") || this._needsSockInitWorkaround = pkgsNeedsSockInitWorkaround.some((pkg) =>
errorStack?.includes("npm-check-updates") || false; errorStack?.includes(pkg)
if (this._isNpmAgent) { );
if (this._needsSockInitWorkaround) {
this.pause(); this.pause();
} }