-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: replace
uriToHost
with nerf-dart
- Loading branch information
1 parent
739962b
commit b8b6bdb
Showing
3 changed files
with
107 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,107 +1,114 @@ | ||
import { URL } from 'url' | ||
import HttpAgent from 'agentkeepalive' | ||
import LRU from 'lru-cache' | ||
import { getProxyAgent, ProxyAgentOptions } from '@pnpm/network.proxy-agent' | ||
import { URL } from "url"; | ||
import HttpAgent from "agentkeepalive"; | ||
import LRU from "lru-cache"; | ||
import nerfDart from "nerf-dart"; | ||
import { getProxyAgent, ProxyAgentOptions } from "@pnpm/network.proxy-agent"; | ||
|
||
const HttpsAgent = HttpAgent.HttpsAgent | ||
const HttpsAgent = HttpAgent.HttpsAgent; | ||
|
||
const DEFAULT_MAX_SOCKETS = 50 | ||
const DEFAULT_MAX_SOCKETS = 50; | ||
|
||
const AGENT_CACHE = new LRU({ max: 50 }) | ||
const AGENT_CACHE = new LRU({ max: 50 }); | ||
|
||
export type AgentOptions = ProxyAgentOptions & { | ||
noProxy?: boolean | string | ||
} | ||
|
||
function uriToHost (uri: string) { | ||
const parsedUri = new URL(uri) | ||
const port = parsedUri.port | ||
const hostname = parsedUri.hostname | ||
let url = `//${hostname}` | ||
if (port) { | ||
url += `:${port}` | ||
} | ||
return `${url}/` | ||
} | ||
noProxy?: boolean | string; | ||
}; | ||
|
||
export function getAgent (uri: string, opts: AgentOptions) { | ||
if ((opts.httpProxy || opts.httpsProxy) && !checkNoProxy(uri, opts)) { | ||
const proxyAgent = getProxyAgent(uri, opts) | ||
if (proxyAgent) return proxyAgent | ||
} | ||
return getNonProxyAgent(uri, opts) | ||
export function getAgent(uri: string, opts: AgentOptions) { | ||
if ((opts.httpProxy || opts.httpsProxy) && !checkNoProxy(uri, opts)) { | ||
const proxyAgent = getProxyAgent(uri, opts); | ||
if (proxyAgent) return proxyAgent; | ||
} | ||
return getNonProxyAgent(uri, opts); | ||
} | ||
|
||
function getNonProxyAgent (uri: string, opts: AgentOptions) { | ||
const parsedUri = new URL(uri) | ||
const host = uriToHost(uri) | ||
const isHttps = parsedUri.protocol === 'https:' | ||
function getNonProxyAgent(uri: string, opts: AgentOptions) { | ||
const parsedUri = new URL(uri); | ||
const host = nerfDart(uri); | ||
const isHttps = parsedUri.protocol === "https:"; | ||
|
||
const clientCertificates = opts.clientCertificates?.[host] ?? null | ||
const clientCertificates = opts.clientCertificates?.[host] ?? null; | ||
|
||
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */ | ||
const key = [ | ||
`https:${isHttps.toString()}`, | ||
`local-address:${opts.localAddress ?? '>no-local-address<'}`, | ||
`strict-ssl:${isHttps ? Boolean(opts.strictSsl).toString() : '>no-strict-ssl<'}`, | ||
`ca:${(isHttps && clientCertificates?.ca || opts.ca?.toString()) || '>no-ca<'}`, | ||
`cert:${(isHttps && clientCertificates?.cert || opts.cert?.toString()) || '>no-cert<'}`, | ||
`key:${(isHttps && clientCertificates?.key || opts.key) || '>no-key<'}`, | ||
].join(':') | ||
/* eslint-enable @typescript-eslint/prefer-nullish-coalescing */ | ||
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */ | ||
const key = [ | ||
`https:${isHttps.toString()}`, | ||
`local-address:${opts.localAddress ?? ">no-local-address<"}`, | ||
`strict-ssl:${ | ||
isHttps ? Boolean(opts.strictSsl).toString() : ">no-strict-ssl<" | ||
}`, | ||
`ca:${ | ||
(isHttps && clientCertificates?.ca) || opts.ca?.toString() || ">no-ca<" | ||
}`, | ||
`cert:${ | ||
(isHttps && clientCertificates?.cert) || | ||
opts.cert?.toString() || | ||
">no-cert<" | ||
}`, | ||
`key:${(isHttps && clientCertificates?.key) || opts.key || ">no-key<"}`, | ||
].join(":"); | ||
/* eslint-enable @typescript-eslint/prefer-nullish-coalescing */ | ||
|
||
if (AGENT_CACHE.peek(key)) { | ||
return AGENT_CACHE.get(key) | ||
} | ||
if (AGENT_CACHE.peek(key)) { | ||
return AGENT_CACHE.get(key); | ||
} | ||
|
||
// If opts.timeout is zero, set the agentTimeout to zero as well. A timeout | ||
// of zero disables the timeout behavior (OS limits still apply). Else, if | ||
// opts.timeout is a non-zero value, set it to timeout + 1, to ensure that | ||
// the node-fetch-npm timeout will always fire first, giving us more | ||
// consistent errors. | ||
const agentTimeout = typeof opts.timeout !== 'number' || opts.timeout === 0 ? 0 : opts.timeout + 1 | ||
// If opts.timeout is zero, set the agentTimeout to zero as well. A timeout | ||
// of zero disables the timeout behavior (OS limits still apply). Else, if | ||
// opts.timeout is a non-zero value, set it to timeout + 1, to ensure that | ||
// the node-fetch-npm timeout will always fire first, giving us more | ||
// consistent errors. | ||
const agentTimeout = | ||
typeof opts.timeout !== "number" || opts.timeout === 0 | ||
? 0 | ||
: opts.timeout + 1; | ||
|
||
// NOTE: localAddress is passed to the agent here even though it is an | ||
// undocumented option of the agent's constructor. | ||
// | ||
// This works because all options of the agent are merged with | ||
// all options of the request: | ||
// https://github.com/nodejs/node/blob/350a95b89faab526de852d417bbb8a3ac823c325/lib/_http_agent.js#L254 | ||
const agent = isHttps | ||
? new HttpsAgent({ | ||
ca: clientCertificates?.ca || opts.ca, | ||
cert: clientCertificates?.cert || opts.cert, | ||
key: clientCertificates?.key || opts.key, | ||
localAddress: opts.localAddress, | ||
maxSockets: opts.maxSockets ?? DEFAULT_MAX_SOCKETS, | ||
rejectUnauthorized: opts.strictSsl, | ||
timeout: agentTimeout, | ||
} as any) // eslint-disable-line @typescript-eslint/no-explicit-any | ||
: new HttpAgent({ | ||
localAddress: opts.localAddress, | ||
maxSockets: opts.maxSockets ?? DEFAULT_MAX_SOCKETS, | ||
timeout: agentTimeout, | ||
} as any) // eslint-disable-line @typescript-eslint/no-explicit-any | ||
AGENT_CACHE.set(key, agent) | ||
return agent | ||
// NOTE: localAddress is passed to the agent here even though it is an | ||
// undocumented option of the agent's constructor. | ||
// | ||
// This works because all options of the agent are merged with | ||
// all options of the request: | ||
// https://github.com/nodejs/node/blob/350a95b89faab526de852d417bbb8a3ac823c325/lib/_http_agent.js#L254 | ||
const agent = isHttps | ||
? new HttpsAgent({ | ||
ca: clientCertificates?.ca || opts.ca, | ||
cert: clientCertificates?.cert || opts.cert, | ||
key: clientCertificates?.key || opts.key, | ||
localAddress: opts.localAddress, | ||
maxSockets: opts.maxSockets ?? DEFAULT_MAX_SOCKETS, | ||
rejectUnauthorized: opts.strictSsl, | ||
timeout: agentTimeout, | ||
} as any) // eslint-disable-line @typescript-eslint/no-explicit-any | ||
: new HttpAgent({ | ||
localAddress: opts.localAddress, | ||
maxSockets: opts.maxSockets ?? DEFAULT_MAX_SOCKETS, | ||
timeout: agentTimeout, | ||
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any | ||
AGENT_CACHE.set(key, agent); | ||
return agent; | ||
} | ||
|
||
function checkNoProxy (uri: string, opts: { noProxy?: boolean | string }) { | ||
const host = new URL(uri).hostname.split('.').filter(x => x).reverse() | ||
if (typeof opts.noProxy === 'string') { | ||
const noproxyArr = opts.noProxy.split(/\s*,\s*/g) | ||
return noproxyArr.some(no => { | ||
const noParts = no.split('.').filter(x => x).reverse() | ||
if (noParts.length === 0) { | ||
return false | ||
} | ||
for (let i = 0; i < noParts.length; i++) { | ||
if (host[i] !== noParts[i]) { | ||
return false | ||
} | ||
} | ||
return true | ||
}) | ||
} | ||
return opts.noProxy | ||
function checkNoProxy(uri: string, opts: { noProxy?: boolean | string }) { | ||
const host = new URL(uri).hostname | ||
.split(".") | ||
.filter((x) => x) | ||
.reverse(); | ||
if (typeof opts.noProxy === "string") { | ||
const noproxyArr = opts.noProxy.split(/\s*,\s*/g); | ||
return noproxyArr.some((no) => { | ||
const noParts = no | ||
.split(".") | ||
.filter((x) => x) | ||
.reverse(); | ||
if (noParts.length === 0) { | ||
return false; | ||
} | ||
for (let i = 0; i < noParts.length; i++) { | ||
if (host[i] !== noParts[i]) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
}); | ||
} | ||
return opts.noProxy; | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters