Skip to content

Commit

Permalink
[proxy-agent] Support for getProxyForUrl option (#160)
Browse files Browse the repository at this point in the history
  • Loading branch information
mceIdo committed May 9, 2023
1 parent 9326064 commit 0bbe335
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/odd-mirrors-nail.md
@@ -0,0 +1,5 @@
---
'proxy-agent': minor
---

Support for `getProxyForUrl` option, to provide proxy address dynamically per different URLs
14 changes: 12 additions & 2 deletions packages/proxy-agent/src/index.ts
Expand Up @@ -3,7 +3,7 @@ import * as https from 'https';
import LRUCache from 'lru-cache';
import { Agent, AgentConnectOpts } from 'agent-base';
import createDebug from 'debug';
import { getProxyForUrl } from 'proxy-from-env';
import { getProxyForUrl as envGetProxyForUrl } from 'proxy-from-env';
import { PacProxyAgent, PacProxyAgentOptions } from 'pac-proxy-agent';
import { HttpProxyAgent, HttpProxyAgentOptions } from 'http-proxy-agent';
import { HttpsProxyAgent, HttpsProxyAgentOptions } from 'https-proxy-agent';
Expand All @@ -21,6 +21,8 @@ type ValidProtocol = (typeof PROTOCOLS)[number];

type AgentConstructor = new (...args: never[]) => Agent;

type GetProxyForUrlCallback = (url: string) => string;

/**
* Supported proxy types.
*/
Expand Down Expand Up @@ -61,6 +63,12 @@ export type ProxyAgentOptions = HttpProxyAgentOptions<''> &
* instance with the proxy agent options passed in.
*/
httpsAgent?: http.Agent;
/**
* A callback for dynamic provision of proxy for url.
* Defaults to standard proxy environment variables,
* see https://www.npmjs.com/package/proxy-from-env for details
*/
getProxyForUrl?: GetProxyForUrlCallback;
};

/**
Expand All @@ -79,6 +87,7 @@ export class ProxyAgent extends Agent {
connectOpts?: ProxyAgentOptions;
httpAgent: http.Agent;
httpsAgent: http.Agent;
getProxyForUrl: GetProxyForUrlCallback;

constructor(opts?: ProxyAgentOptions) {
super(opts);
Expand All @@ -87,6 +96,7 @@ export class ProxyAgent extends Agent {
this.httpAgent = opts?.httpAgent || new http.Agent(opts);
this.httpsAgent =
opts?.httpsAgent || new https.Agent(opts as https.AgentOptions);
this.getProxyForUrl = opts?.getProxyForUrl || envGetProxyForUrl;
}

async connect(
Expand All @@ -97,7 +107,7 @@ export class ProxyAgent extends Agent {
const protocol = secureEndpoint ? 'https:' : 'http:';
const host = req.getHeader('host');
const url = new URL(req.path, `${protocol}//${host}`).href;
const proxy = getProxyForUrl(url);
const proxy = this.getProxyForUrl(url);

if (!proxy) {
debug('Proxy not enabled for URL: %o', url);
Expand Down
26 changes: 26 additions & 0 deletions packages/proxy-agent/test/test.ts
Expand Up @@ -251,5 +251,31 @@ describe('ProxyAgent', () => {
HttpsProxyAgent
);
});

it('should call provided function with 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: (u) => {
gotCall = true;
urlParameter = u;
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);
});
});
});

1 comment on commit 0bbe335

@vercel
Copy link

@vercel vercel bot commented on 0bbe335 May 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

proxy-agents – ./

proxy-agents.vercel.app
proxy-agents-tootallnate.vercel.app
proxy-agents-git-main-tootallnate.vercel.app

Please sign in to comment.