From 8ff9faa388149f7c2edde39231de2afc439055c2 Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Thu, 18 May 2023 04:29:48 -0400 Subject: [PATCH] [https-proxy-agent] Support dynamic headers (#174) --- .changeset/tidy-jobs-refuse.md | 5 +++++ packages/https-proxy-agent/src/index.ts | 11 +++++++---- packages/https-proxy-agent/test/test.ts | 25 ++++++++++++++++++++++++- 3 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 .changeset/tidy-jobs-refuse.md diff --git a/.changeset/tidy-jobs-refuse.md b/.changeset/tidy-jobs-refuse.md new file mode 100644 index 00000000..b64ef874 --- /dev/null +++ b/.changeset/tidy-jobs-refuse.md @@ -0,0 +1,5 @@ +--- +'https-proxy-agent': minor +--- + +"headers" option can now be a function diff --git a/packages/https-proxy-agent/src/index.ts b/packages/https-proxy-agent/src/index.ts index 8244b1c7..6bdd9ae5 100644 --- a/packages/https-proxy-agent/src/index.ts +++ b/packages/https-proxy-agent/src/index.ts @@ -3,7 +3,7 @@ import * as tls from 'tls'; import * as http from 'http'; import assert from 'assert'; import createDebug from 'debug'; -import { OutgoingHttpHeaders } from 'http'; +import type { OutgoingHttpHeaders } from 'http'; import { Agent, AgentConnectOpts } from 'agent-base'; import { parseProxyResponse } from './parse-proxy-response'; @@ -25,7 +25,7 @@ type ConnectOpts = { export type HttpsProxyAgentOptions = ConnectOpts & http.AgentOptions & { - headers?: OutgoingHttpHeaders; + headers?: OutgoingHttpHeaders | (() => OutgoingHttpHeaders); }; /** @@ -44,7 +44,7 @@ export class HttpsProxyAgent extends Agent { static protocols = ['http', 'https'] as const; readonly proxy: URL; - proxyHeaders: OutgoingHttpHeaders; + proxyHeaders: OutgoingHttpHeaders | (() => OutgoingHttpHeaders); connectOpts: net.TcpNetConnectOpts & tls.ConnectionOptions; get secureProxy() { @@ -101,7 +101,10 @@ export class HttpsProxyAgent extends Agent { socket = net.connect(this.connectOpts); } - const headers: OutgoingHttpHeaders = { ...this.proxyHeaders }; + const headers: OutgoingHttpHeaders = + typeof this.proxyHeaders === 'function' + ? this.proxyHeaders() + : { ...this.proxyHeaders }; const host = net.isIPv6(opts.host) ? `[${opts.host}]` : opts.host; let payload = `CONNECT ${host}:${opts.port} HTTP/1.1\r\n`; diff --git a/packages/https-proxy-agent/test/test.ts b/packages/https-proxy-agent/test/test.ts index 93bd43e9..8152ea4a 100644 --- a/packages/https-proxy-agent/test/test.ts +++ b/packages/https-proxy-agent/test/test.ts @@ -188,7 +188,7 @@ describe('HttpsProxyAgent', () => { assert.equal('ECONNREFUSED', err.code); }); - it('should allow custom proxy "headers"', async () => { + it('should allow custom proxy "headers" object', async () => { const agent = new HttpsProxyAgent(serverUrl, { headers: { Foo: 'bar', @@ -205,6 +205,29 @@ describe('HttpsProxyAgent', () => { socket.destroy(); }); + it('should allow custom proxy "headers" function', async () => { + let count = 1; + const agent = new HttpsProxyAgent(serverUrl, { + headers: () => ({ number: count++ }), + }); + + const connectPromise = once(server, 'connect'); + http.get({ agent }); + + const [req, socket] = await connectPromise; + assert.equal('CONNECT', req.method); + assert.equal('1', req.headers.number); + socket.destroy(); + + const connectPromise2 = once(server, 'connect'); + http.get({ agent }); + + const [req2, socket2] = await connectPromise2; + assert.equal('CONNECT', req2.method); + assert.equal('2', req2.headers.number); + socket2.destroy(); + }); + it('should work with `keepAlive: true`', async () => { server.on('request', (req, res) => { res.end(JSON.stringify(req.headers));