From e7e0e56d1f260c80a2c3660b6a015b38f83e0b7e Mon Sep 17 00:00:00 2001 From: Mark Yen Date: Mon, 12 Feb 2024 10:11:58 -0800 Subject: [PATCH] [proxy-agent] Allow asynchronous `getProxyForUrl` (#275) This allows users to use an asynchronous getProxyForUrl in case they need to do asynchronous operations to resolve the correct proxy URL. This can be the case, for example, if using Electron.Session.resolveProxy(url). --- .changeset/nice-pillows-type.md | 5 +++++ packages/proxy-agent/src/index.ts | 4 ++-- packages/proxy-agent/test/test.ts | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 .changeset/nice-pillows-type.md diff --git a/.changeset/nice-pillows-type.md b/.changeset/nice-pillows-type.md new file mode 100644 index 00000000..9d0045de --- /dev/null +++ b/.changeset/nice-pillows-type.md @@ -0,0 +1,5 @@ +--- +'proxy-agent': minor +--- + +Allow `getProxyForUrl()` option to return a Promise diff --git a/packages/proxy-agent/src/index.ts b/packages/proxy-agent/src/index.ts index c051f8a2..496e185a 100644 --- a/packages/proxy-agent/src/index.ts +++ b/packages/proxy-agent/src/index.ts @@ -22,7 +22,7 @@ type ValidProtocol = (typeof PROTOCOLS)[number]; type AgentConstructor = new (...args: never[]) => Agent; -type GetProxyForUrlCallback = (url: string) => string; +type GetProxyForUrlCallback = (url: string) => string | Promise; /** * Supported proxy types. @@ -115,7 +115,7 @@ export class ProxyAgent extends Agent { : 'http:'; const host = req.getHeader('host'); const url = new URL(req.path, `${protocol}//${host}`).href; - const proxy = this.getProxyForUrl(url); + const proxy = await this.getProxyForUrl(url); if (!proxy) { debug('Proxy not enabled for URL: %o', url); diff --git a/packages/proxy-agent/test/test.ts b/packages/proxy-agent/test/test.ts index 5f6de6e7..2544d182 100644 --- a/packages/proxy-agent/test/test.ts +++ b/packages/proxy-agent/test/test.ts @@ -2,6 +2,7 @@ import * as fs from 'fs'; import * as http from 'http'; import * as https from 'https'; import { URL } from 'url'; +import { promisify } from 'util'; import { once } from 'events'; import assert from 'assert'; import WebSocket, { WebSocketServer } from 'ws'; @@ -287,6 +288,33 @@ describe('ProxyAgent', () => { assert(gotCall); assert(requestUrl.href === urlParameter); }); + + it('should call provided function with asynchronous getProxyForUrl option', async () => { + let gotCall = false; + let urlParameter = ''; + httpsServer.once('request', function (req, res) { + res.end(JSON.stringify(req.headers)); + }); + + const agent = new ProxyAgent({ + rejectUnauthorized: false, + getProxyForUrl: async(u) => { + gotCall = true; + urlParameter = u; + await promisify(setTimeout)(1); + return httpsProxyServerUrl.href; + }, + }); + const requestUrl = new URL('/test', httpsServerUrl); + const res = await req(requestUrl, { + agent, + rejectUnauthorized: false, + }); + const body = await json(res); + assert(httpsServerUrl.host === body.host); + assert(gotCall); + assert(requestUrl.href === urlParameter); + }); }); describe('"ws" module', () => {