From b5f19ce974588a9f76a614d546631f1e8a2e5043 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Thu, 13 Nov 2025 10:35:06 -0500 Subject: [PATCH] feat: add bypassCustomProtocolHandlers option to net.request (#48882) * feat: add bypassCustomProtocolHandlers option to net.request Co-authored-by: Kai * style: fix lint errors in api-protocol-spec Co-authored-by: Kai --------- Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Kai --- docs/api/client-request.md | 5 +++++ lib/common/api/net-client-request.ts | 3 ++- spec/api-protocol-spec.ts | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/api/client-request.md b/docs/api/client-request.md index d6e27d6deb95..398290f1eef9 100644 --- a/docs/api/client-request.md +++ b/docs/api/client-request.md @@ -25,6 +25,11 @@ following properties: with which the request is associated. Defaults to the empty string. The `session` option supersedes `partition`. Thus if a `session` is explicitly specified, `partition` is ignored. + * `bypassCustomProtocolHandlers` boolean (optional) - When set to `true`, + custom protocol handlers registered for the request's URL scheme will not be + called. This allows forwarding an intercepted request to the built-in + handler. [webRequest](web-request.md) handlers will still be triggered + when bypassing custom protocols. Defaults to `false`. * `credentials` string (optional) - Can be `include`, `omit` or `same-origin`. Whether to send [credentials](https://fetch.spec.whatwg.org/#credentials) with this diff --git a/lib/common/api/net-client-request.ts b/lib/common/api/net-client-request.ts index a2682da670d2..add5e24537f7 100644 --- a/lib/common/api/net-client-request.ts +++ b/lib/common/api/net-client-request.ts @@ -289,7 +289,8 @@ function parseOptions (optionsIn: ClientRequestConstructorOptions | string): Nod referrerPolicy: options.referrerPolicy, cache: options.cache, allowNonHttpProtocols: Object.hasOwn(options, kAllowNonHttpProtocols), - priority: options.priority + priority: options.priority, + bypassCustomProtocolHandlers: options.bypassCustomProtocolHandlers }; if ('priorityIncremental' in options) { urlLoaderOptions.priorityIncremental = options.priorityIncremental; diff --git a/spec/api-protocol-spec.ts b/spec/api-protocol-spec.ts index 415ed5fdafe4..4a2f8b10c9c4 100644 --- a/spec/api-protocol-spec.ts +++ b/spec/api-protocol-spec.ts @@ -15,6 +15,7 @@ import * as webStream from 'node:stream/web'; import { setTimeout } from 'node:timers/promises'; import * as url from 'node:url'; +import { collectStreamBody, getResponse } from './lib/net-helpers'; import { listen, defer, ifit } from './lib/spec-helpers'; import { WebmGenerator } from './lib/video-helpers'; import { closeAllWindows, closeWindow } from './lib/window-helpers'; @@ -1578,6 +1579,22 @@ describe('protocol module', () => { expect(await net.fetch(url, { bypassCustomProtocolHandlers: true }).then(r => r.text())).to.equal('default'); }); + it('can bypass intercepted protocol handlers with net.request', async () => { + protocol.handle('http', () => new Response('custom')); + defer(() => { protocol.unhandle('http'); }); + const server = http.createServer((req, res) => { + res.end('default'); + }); + defer(() => server.close()); + const { url } = await listen(server); + // Make a request using net.request with bypassCustomProtocolHandlers: true + const request = net.request({ method: 'GET', url, bypassCustomProtocolHandlers: true }); + const response = await getResponse(request); + const body = await collectStreamBody(response); + expect(response.statusCode).to.equal(200); + expect(body).to.equal('default'); + }); + it('bypassing custom protocol handlers also bypasses new protocols', async () => { protocol.handle('app', () => new Response('custom')); defer(() => { protocol.unhandle('app'); });