diff options
author | RaindropsSys <raindrops@equestria.dev> | 2023-10-24 17:43:37 +0200 |
---|---|---|
committer | RaindropsSys <raindrops@equestria.dev> | 2023-10-24 17:43:37 +0200 |
commit | ae187b6d75c8079da0be1dc288613bad8466fe61 (patch) | |
tree | 5ea0d34185a2270f29ffaa65e1f5258028d7d5d0 /desktop/node_modules/global-agent/src | |
download | mist-ae187b6d75c8079da0be1dc288613bad8466fe61.tar.gz mist-ae187b6d75c8079da0be1dc288613bad8466fe61.tar.bz2 mist-ae187b6d75c8079da0be1dc288613bad8466fe61.zip |
Initial commit
Diffstat (limited to 'desktop/node_modules/global-agent/src')
17 files changed, 803 insertions, 0 deletions
diff --git a/desktop/node_modules/global-agent/src/Logger.js b/desktop/node_modules/global-agent/src/Logger.js new file mode 100644 index 0000000..166f1e4 --- /dev/null +++ b/desktop/node_modules/global-agent/src/Logger.js @@ -0,0 +1,10 @@ +// @flow + +import Roarr from 'roarr'; + +const Logger = Roarr + .child({ + package: 'global-agent', + }); + +export default Logger; diff --git a/desktop/node_modules/global-agent/src/classes/Agent.js b/desktop/node_modules/global-agent/src/classes/Agent.js new file mode 100644 index 0000000..801dd1f --- /dev/null +++ b/desktop/node_modules/global-agent/src/classes/Agent.js @@ -0,0 +1,212 @@ +// @flow + +import { + serializeError, +} from 'serialize-error'; +import { + boolean, +} from 'boolean'; +import Logger from '../Logger'; +import type { + AgentType, + GetUrlProxyMethodType, + IsProxyConfiguredMethodType, + MustUrlUseProxyMethodType, + ProtocolType, +} from '../types'; + +const log = Logger.child({ + namespace: 'Agent', +}); + +let requestId = 0; + +class Agent { + defaultPort: number; + + protocol: ProtocolType; + + fallbackAgent: AgentType; + + isProxyConfigured: IsProxyConfiguredMethodType; + + mustUrlUseProxy: MustUrlUseProxyMethodType; + + getUrlProxy: GetUrlProxyMethodType; + + socketConnectionTimeout: number; + + constructor ( + isProxyConfigured: IsProxyConfiguredMethodType, + mustUrlUseProxy: MustUrlUseProxyMethodType, + getUrlProxy: GetUrlProxyMethodType, + fallbackAgent: AgentType, + socketConnectionTimeout: number, + ) { + this.fallbackAgent = fallbackAgent; + this.isProxyConfigured = isProxyConfigured; + this.mustUrlUseProxy = mustUrlUseProxy; + this.getUrlProxy = getUrlProxy; + this.socketConnectionTimeout = socketConnectionTimeout; + } + + addRequest (request: *, configuration: *) { + let requestUrl; + + // It is possible that addRequest was constructed for a proxied request already, e.g. + // "request" package does this when it detects that a proxy should be used + // https://github.com/request/request/blob/212570b6971a732b8dd9f3c73354bcdda158a737/request.js#L402 + // https://gist.github.com/gajus/e2074cd3b747864ffeaabbd530d30218 + if (request.path.startsWith('http://') || request.path.startsWith('https://')) { + requestUrl = request.path; + } else { + requestUrl = this.protocol + '//' + (configuration.hostname || configuration.host) + (configuration.port === 80 || configuration.port === 443 ? '' : ':' + configuration.port) + request.path; + } + + if (!this.isProxyConfigured()) { + log.trace({ + destination: requestUrl, + }, 'not proxying request; GLOBAL_AGENT.HTTP_PROXY is not configured'); + + // $FlowFixMe It appears that Flow is missing the method description. + this.fallbackAgent.addRequest(request, configuration); + + return; + } + + if (!this.mustUrlUseProxy(requestUrl)) { + log.trace({ + destination: requestUrl, + }, 'not proxying request; url matches GLOBAL_AGENT.NO_PROXY'); + + // $FlowFixMe It appears that Flow is missing the method description. + this.fallbackAgent.addRequest(request, configuration); + + return; + } + + const currentRequestId = requestId++; + + const proxy = this.getUrlProxy(requestUrl); + + if (this.protocol === 'http:') { + request.path = requestUrl; + + if (proxy.authorization) { + request.setHeader('proxy-authorization', 'Basic ' + Buffer.from(proxy.authorization).toString('base64')); + } + } + + log.trace({ + destination: requestUrl, + proxy: 'http://' + proxy.hostname + ':' + proxy.port, + requestId: currentRequestId, + }, 'proxying request'); + + request.on('error', (error) => { + log.error({ + error: serializeError(error), + }, 'request error'); + }); + + request.once('response', (response) => { + log.trace({ + headers: response.headers, + requestId: currentRequestId, + statusCode: response.statusCode, + }, 'proxying response'); + }); + + request.shouldKeepAlive = false; + + const connectionConfiguration = { + host: configuration.hostname || configuration.host, + port: configuration.port || 80, + proxy, + tls: {}, + }; + + // add optional tls options for https requests. + // @see https://nodejs.org/docs/latest-v12.x/api/https.html#https_https_request_url_options_callback : + // > The following additional options from tls.connect() + // > - https://nodejs.org/docs/latest-v12.x/api/tls.html#tls_tls_connect_options_callback - + // > are also accepted: + // > ca, cert, ciphers, clientCertEngine, crl, dhparam, ecdhCurve, honorCipherOrder, + // > key, passphrase, pfx, rejectUnauthorized, secureOptions, secureProtocol, servername, sessionIdContext. + if (this.protocol === 'https:') { + connectionConfiguration.tls = { + ca: configuration.ca, + cert: configuration.cert, + ciphers: configuration.ciphers, + clientCertEngine: configuration.clientCertEngine, + crl: configuration.crl, + dhparam: configuration.dhparam, + ecdhCurve: configuration.ecdhCurve, + honorCipherOrder: configuration.honorCipherOrder, + key: configuration.key, + passphrase: configuration.passphrase, + pfx: configuration.pfx, + rejectUnauthorized: configuration.rejectUnauthorized, + secureOptions: configuration.secureOptions, + secureProtocol: configuration.secureProtocol, + servername: configuration.servername || connectionConfiguration.host, + sessionIdContext: configuration.sessionIdContext, + }; + + // This is not ideal because there is no way to override this setting using `tls` configuration if `NODE_TLS_REJECT_UNAUTHORIZED=0`. + // However, popular HTTP clients (such as https://github.com/sindresorhus/got) come with pre-configured value for `rejectUnauthorized`, + // which makes it impossible to override that value globally and respect `rejectUnauthorized` for specific requests only. + // + // eslint-disable-next-line no-process-env + if (typeof process.env.NODE_TLS_REJECT_UNAUTHORIZED === 'string' && boolean(process.env.NODE_TLS_REJECT_UNAUTHORIZED) === false) { + connectionConfiguration.tls.rejectUnauthorized = false; + } + } + + // $FlowFixMe It appears that Flow is missing the method description. + this.createConnection(connectionConfiguration, (error, socket) => { + log.trace({ + target: connectionConfiguration, + }, 'connecting'); + + // @see https://github.com/nodejs/node/issues/5757#issuecomment-305969057 + if (socket) { + socket.setTimeout(this.socketConnectionTimeout, () => { + socket.destroy(); + }); + + socket.once('connect', () => { + log.trace({ + target: connectionConfiguration, + }, 'connected'); + + socket.setTimeout(0); + }); + + socket.once('secureConnect', () => { + log.trace({ + target: connectionConfiguration, + }, 'connected (secure)'); + + socket.setTimeout(0); + }); + } + + if (error) { + request.emit('error', error); + } else { + log.debug('created socket'); + + socket.on('error', (socketError) => { + log.error({ + error: serializeError(socketError), + }, 'socket error'); + }); + + request.onSocket(socket); + } + }); + } +} + +export default Agent; diff --git a/desktop/node_modules/global-agent/src/classes/HttpProxyAgent.js b/desktop/node_modules/global-agent/src/classes/HttpProxyAgent.js new file mode 100644 index 0000000..8b9b471 --- /dev/null +++ b/desktop/node_modules/global-agent/src/classes/HttpProxyAgent.js @@ -0,0 +1,30 @@ +// @flow + +import net from 'net'; +import type { + ConnectionCallbackType, + ConnectionConfigurationType, +} from '../types'; +import Agent from './Agent'; + +class HttpProxyAgent extends Agent { + // @see https://github.com/sindresorhus/eslint-plugin-unicorn/issues/169#issuecomment-486980290 + // eslint-disable-next-line unicorn/prevent-abbreviations + constructor (...args: *) { + super(...args); + + this.protocol = 'http:'; + this.defaultPort = 80; + } + + createConnection (configuration: ConnectionConfigurationType, callback: ConnectionCallbackType) { + const socket = net.connect( + configuration.proxy.port, + configuration.proxy.hostname, + ); + + callback(null, socket); + } +} + +export default HttpProxyAgent; diff --git a/desktop/node_modules/global-agent/src/classes/HttpsProxyAgent.js b/desktop/node_modules/global-agent/src/classes/HttpsProxyAgent.js new file mode 100644 index 0000000..24d724f --- /dev/null +++ b/desktop/node_modules/global-agent/src/classes/HttpsProxyAgent.js @@ -0,0 +1,54 @@ +// @flow + +import net from 'net'; +import tls from 'tls'; +import type { + ConnectionCallbackType, + ConnectionConfigurationType, +} from '../types'; +import Agent from './Agent'; + +class HttpsProxyAgent extends Agent { + // eslint-disable-next-line unicorn/prevent-abbreviations + constructor (...args: *) { + super(...args); + + this.protocol = 'https:'; + this.defaultPort = 443; + } + + createConnection (configuration: ConnectionConfigurationType, callback: ConnectionCallbackType) { + const socket = net.connect( + configuration.proxy.port, + configuration.proxy.hostname, + ); + + socket.on('error', (error) => { + callback(error); + }); + + socket.once('data', () => { + const secureSocket = tls.connect({ + ...configuration.tls, + socket, + }); + + callback(null, secureSocket); + }); + + let connectMessage = ''; + + connectMessage += 'CONNECT ' + configuration.host + ':' + configuration.port + ' HTTP/1.1\r\n'; + connectMessage += 'Host: ' + configuration.host + ':' + configuration.port + '\r\n'; + + if (configuration.proxy.authorization) { + connectMessage += 'Proxy-Authorization: Basic ' + Buffer.from(configuration.proxy.authorization).toString('base64') + '\r\n'; + } + + connectMessage += '\r\n'; + + socket.write(connectMessage); + } +} + +export default HttpsProxyAgent; diff --git a/desktop/node_modules/global-agent/src/classes/index.js b/desktop/node_modules/global-agent/src/classes/index.js new file mode 100644 index 0000000..9e8418a --- /dev/null +++ b/desktop/node_modules/global-agent/src/classes/index.js @@ -0,0 +1,5 @@ +// @flow + +export {default as Agent} from './Agent'; +export {default as HttpProxyAgent} from './HttpProxyAgent'; +export {default as HttpsProxyAgent} from './HttpsProxyAgent'; diff --git a/desktop/node_modules/global-agent/src/errors.js b/desktop/node_modules/global-agent/src/errors.js new file mode 100644 index 0000000..d93ba6f --- /dev/null +++ b/desktop/node_modules/global-agent/src/errors.js @@ -0,0 +1,15 @@ +// @flow + +/* eslint-disable fp/no-class, fp/no-this */ + +import ExtendableError from 'es6-error'; + +export class UnexpectedStateError extends ExtendableError { + code: string; + + constructor (message: string, code: string = 'UNEXPECTED_STATE_ERROR') { + super(message); + + this.code = code; + } +} diff --git a/desktop/node_modules/global-agent/src/factories/createGlobalProxyAgent.js b/desktop/node_modules/global-agent/src/factories/createGlobalProxyAgent.js new file mode 100644 index 0000000..d515a9d --- /dev/null +++ b/desktop/node_modules/global-agent/src/factories/createGlobalProxyAgent.js @@ -0,0 +1,197 @@ +// @flow + +import http from 'http'; +import https from 'https'; +import { + boolean as parseBoolean, +} from 'boolean'; +import semver from 'semver'; +import Logger from '../Logger'; +import { + HttpProxyAgent, + HttpsProxyAgent, +} from '../classes'; +import { + UnexpectedStateError, +} from '../errors'; +import { + bindHttpMethod, + isUrlMatchingNoProxy, + parseProxyUrl, +} from '../utilities'; +import type { + ProxyAgentConfigurationInputType, + ProxyAgentConfigurationType, +} from '../types'; +import createProxyController from './createProxyController'; + +const httpGet = http.get; +const httpRequest = http.request; +const httpsGet = https.get; +const httpsRequest = https.request; + +const log = Logger.child({ + namespace: 'createGlobalProxyAgent', +}); + +const defaultConfigurationInput = { + environmentVariableNamespace: undefined, + forceGlobalAgent: undefined, + socketConnectionTimeout: 60000, +}; + +const omitUndefined = (subject) => { + const keys = Object.keys(subject); + + const result = {}; + + for (const key of keys) { + const value = subject[key]; + + if (value !== undefined) { + result[key] = value; + } + } + + return result; +}; + +const createConfiguration = (configurationInput: ProxyAgentConfigurationInputType): ProxyAgentConfigurationType => { + // eslint-disable-next-line no-process-env + const environment = process.env; + + const defaultConfiguration = { + environmentVariableNamespace: typeof environment.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE === 'string' ? environment.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE : 'GLOBAL_AGENT_', + forceGlobalAgent: typeof environment.GLOBAL_AGENT_FORCE_GLOBAL_AGENT === 'string' ? parseBoolean(environment.GLOBAL_AGENT_FORCE_GLOBAL_AGENT) : true, + socketConnectionTimeout: typeof environment.GLOBAL_AGENT_SOCKET_CONNECTION_TIMEOUT === 'string' ? Number.parseInt(environment.GLOBAL_AGENT_SOCKET_CONNECTION_TIMEOUT, 10) : defaultConfigurationInput.socketConnectionTimeout, + }; + + // $FlowFixMe + return { + ...defaultConfiguration, + ...omitUndefined(configurationInput), + }; +}; + +export default (configurationInput: ProxyAgentConfigurationInputType = defaultConfigurationInput) => { + const configuration = createConfiguration(configurationInput); + + const proxyController = createProxyController(); + + // eslint-disable-next-line no-process-env + proxyController.HTTP_PROXY = process.env[configuration.environmentVariableNamespace + 'HTTP_PROXY'] || null; + + // eslint-disable-next-line no-process-env + proxyController.HTTPS_PROXY = process.env[configuration.environmentVariableNamespace + 'HTTPS_PROXY'] || null; + + // eslint-disable-next-line no-process-env + proxyController.NO_PROXY = process.env[configuration.environmentVariableNamespace + 'NO_PROXY'] || null; + + log.info({ + configuration, + state: proxyController, + }, 'global agent has been initialized'); + + const mustUrlUseProxy = (getProxy) => { + return (url) => { + if (!getProxy()) { + return false; + } + + if (!proxyController.NO_PROXY) { + return true; + } + + return !isUrlMatchingNoProxy(url, proxyController.NO_PROXY); + }; + }; + + const getUrlProxy = (getProxy) => { + return () => { + const proxy = getProxy(); + + if (!proxy) { + throw new UnexpectedStateError('HTTP(S) proxy must be configured.'); + } + + return parseProxyUrl(proxy); + }; + }; + + const getHttpProxy = () => { + return proxyController.HTTP_PROXY; + }; + + const BoundHttpProxyAgent = class extends HttpProxyAgent { + constructor () { + super( + () => { + return getHttpProxy(); + }, + mustUrlUseProxy(getHttpProxy), + getUrlProxy(getHttpProxy), + http.globalAgent, + configuration.socketConnectionTimeout, + ); + } + }; + + const httpAgent = new BoundHttpProxyAgent(); + + const getHttpsProxy = () => { + return proxyController.HTTPS_PROXY || proxyController.HTTP_PROXY; + }; + + const BoundHttpsProxyAgent = class extends HttpsProxyAgent { + constructor () { + super( + () => { + return getHttpsProxy(); + }, + mustUrlUseProxy(getHttpsProxy), + getUrlProxy(getHttpsProxy), + https.globalAgent, + configuration.socketConnectionTimeout, + ); + } + }; + + const httpsAgent = new BoundHttpsProxyAgent(); + + // Overriding globalAgent was added in v11.7. + // @see https://nodejs.org/uk/blog/release/v11.7.0/ + if (semver.gte(process.version, 'v11.7.0')) { + // @see https://github.com/facebook/flow/issues/7670 + // $FlowFixMe + http.globalAgent = httpAgent; + + // $FlowFixMe + https.globalAgent = httpsAgent; + } + + // The reason this logic is used in addition to overriding http(s).globalAgent + // is because there is no guarantee that we set http(s).globalAgent variable + // before an instance of http(s).Agent has been already constructed by someone, + // e.g. Stripe SDK creates instances of http(s).Agent at the top-level. + // @see https://github.com/gajus/global-agent/pull/13 + // + // We still want to override http(s).globalAgent when possible to enable logic + // in `bindHttpMethod`. + if (semver.gte(process.version, 'v10.0.0')) { + // $FlowFixMe + http.get = bindHttpMethod(httpGet, httpAgent, configuration.forceGlobalAgent); + + // $FlowFixMe + http.request = bindHttpMethod(httpRequest, httpAgent, configuration.forceGlobalAgent); + + // $FlowFixMe + https.get = bindHttpMethod(httpsGet, httpsAgent, configuration.forceGlobalAgent); + + // $FlowFixMe + https.request = bindHttpMethod(httpsRequest, httpsAgent, configuration.forceGlobalAgent); + } else { + log.warn('attempt to initialize global-agent in unsupported Node.js version was ignored'); + } + + return proxyController; +}; diff --git a/desktop/node_modules/global-agent/src/factories/createProxyController.js b/desktop/node_modules/global-agent/src/factories/createProxyController.js new file mode 100644 index 0000000..5805ec8 --- /dev/null +++ b/desktop/node_modules/global-agent/src/factories/createProxyController.js @@ -0,0 +1,46 @@ +// @flow + +import Logger from '../Logger'; + +type ProxyControllerType = {| + HTTP_PROXY: string | null, + HTTPS_PROXY: string | null, + NO_PROXY: string | null, +|}; + +const log = Logger.child({ + namespace: 'createProxyController', +}); + +const KNOWN_PROPERTY_NAMES = [ + 'HTTP_PROXY', + 'HTTPS_PROXY', + 'NO_PROXY', +]; + +export default (): ProxyControllerType => { + // eslint-disable-next-line fp/no-proxy + return new Proxy({ + HTTP_PROXY: null, + HTTPS_PROXY: null, + NO_PROXY: null, + }, { + set: (subject, name, value) => { + if (!KNOWN_PROPERTY_NAMES.includes(name)) { + throw new Error('Cannot set an unmapped property "' + name + '".'); + } + + subject[name] = value; + + log.info({ + change: { + name, + value, + }, + newConfiguration: subject, + }, 'configuration changed'); + + return true; + }, + }); +}; diff --git a/desktop/node_modules/global-agent/src/factories/index.js b/desktop/node_modules/global-agent/src/factories/index.js new file mode 100644 index 0000000..c16eca6 --- /dev/null +++ b/desktop/node_modules/global-agent/src/factories/index.js @@ -0,0 +1,4 @@ +// @flow + +export {default as createGlobalProxyAgent} from './createGlobalProxyAgent'; +export {default as createProxyController} from './createProxyController'; diff --git a/desktop/node_modules/global-agent/src/index.js b/desktop/node_modules/global-agent/src/index.js new file mode 100644 index 0000000..14da1ba --- /dev/null +++ b/desktop/node_modules/global-agent/src/index.js @@ -0,0 +1,4 @@ +// @flow + +export {bootstrap} from './routines'; +export {createGlobalProxyAgent} from './factories'; diff --git a/desktop/node_modules/global-agent/src/routines/bootstrap.js b/desktop/node_modules/global-agent/src/routines/bootstrap.js new file mode 100644 index 0000000..038feb3 --- /dev/null +++ b/desktop/node_modules/global-agent/src/routines/bootstrap.js @@ -0,0 +1,25 @@ +// @flow + +import Logger from '../Logger'; +import { + createGlobalProxyAgent, +} from '../factories'; +import type { + ProxyAgentConfigurationInputType, +} from '../types'; + +const log = Logger.child({ + namespace: 'bootstrap', +}); + +export default (configurationInput?: ProxyAgentConfigurationInputType): boolean => { + if (global.GLOBAL_AGENT) { + log.warn('found global.GLOBAL_AGENT; second attempt to bootstrap global-agent was ignored'); + + return false; + } + + global.GLOBAL_AGENT = createGlobalProxyAgent(configurationInput); + + return true; +}; diff --git a/desktop/node_modules/global-agent/src/routines/index.js b/desktop/node_modules/global-agent/src/routines/index.js new file mode 100644 index 0000000..e47a8a0 --- /dev/null +++ b/desktop/node_modules/global-agent/src/routines/index.js @@ -0,0 +1,3 @@ +// @flow + +export {default as bootstrap} from './bootstrap'; diff --git a/desktop/node_modules/global-agent/src/types.js b/desktop/node_modules/global-agent/src/types.js new file mode 100644 index 0000000..e2f1a99 --- /dev/null +++ b/desktop/node_modules/global-agent/src/types.js @@ -0,0 +1,66 @@ +// @flow + +import { + Socket, +} from 'net'; +import { + TLSSocket, +} from 'tls'; +import { + Agent as HttpAgent, +} from 'http'; +import { + Agent as HttpsAgent, +} from 'https'; + +export type ProxyConfigurationType = {| + +authorization: string, + +hostname: string, + +port: number, +|}; + +export type TlsConfigurationType = {| + +ca?: string, + +cert?: string, + +ciphers?: string, + +clientCertEngine?: string, + +crl?: string, + +dhparam?: string, + +ecdhCurve?: string, + +honorCipherOrder?: boolean, + +key?: string, + +passphrase?: string, + +pfx?: string, + +rejectUnauthorized?: boolean, + +secureOptions?: number, + +secureProtocol?: string, + +servername?: string, + +sessionIdContext?: string, +|}; + +export type ConnectionConfigurationType = {| + +host: string, + +port: number, + +tls?: TlsConfigurationType, + +proxy: ProxyConfigurationType, +|}; + +export type ConnectionCallbackType = (error: Error | null, socket?: Socket | TLSSocket) => void; + +export type AgentType = HttpAgent | HttpsAgent; +export type IsProxyConfiguredMethodType = () => boolean; +export type MustUrlUseProxyMethodType = (url: string) => boolean; +export type GetUrlProxyMethodType = (url: string) => ProxyConfigurationType; +export type ProtocolType = 'http:' | 'https:'; + +export type ProxyAgentConfigurationInputType = {| + +environmentVariableNamespace?: string, + +forceGlobalAgent?: boolean, + +socketConnectionTimeout?: number, +|}; + +export type ProxyAgentConfigurationType = {| + +environmentVariableNamespace: string, + +forceGlobalAgent: boolean, + +socketConnectionTimeout: number, +|}; diff --git a/desktop/node_modules/global-agent/src/utilities/bindHttpMethod.js b/desktop/node_modules/global-agent/src/utilities/bindHttpMethod.js new file mode 100644 index 0000000..f8859b5 --- /dev/null +++ b/desktop/node_modules/global-agent/src/utilities/bindHttpMethod.js @@ -0,0 +1,54 @@ +// @flow + +import http from 'http'; +import https from 'https'; + +type AgentType = http.Agent | https.Agent; + +// eslint-disable-next-line flowtype/no-weak-types +export default (originalMethod: Function, agent: AgentType, forceGlobalAgent: boolean) => { + // eslint-disable-next-line unicorn/prevent-abbreviations + return (...args: *) => { + let url; + let options; + let callback; + + if (typeof args[0] === 'string' || args[0] instanceof URL) { + url = args[0]; + + if (typeof args[1] === 'function') { + options = {}; + callback = args[1]; + } else { + options = { + ...args[1], + }; + callback = args[2]; + } + } else { + options = { + ...args[0], + }; + callback = args[1]; + } + + if (forceGlobalAgent) { + options.agent = agent; + } else { + if (!options.agent) { + options.agent = agent; + } + + if (options.agent === http.globalAgent || options.agent === https.globalAgent) { + options.agent = agent; + } + } + + if (url) { + // $FlowFixMe + return originalMethod(url, options, callback); + } else { + return originalMethod(options, callback); + } + }; +}; diff --git a/desktop/node_modules/global-agent/src/utilities/index.js b/desktop/node_modules/global-agent/src/utilities/index.js new file mode 100644 index 0000000..3412387 --- /dev/null +++ b/desktop/node_modules/global-agent/src/utilities/index.js @@ -0,0 +1,5 @@ +// @flow + +export {default as bindHttpMethod} from './bindHttpMethod'; +export {default as isUrlMatchingNoProxy} from './isUrlMatchingNoProxy'; +export {default as parseProxyUrl} from './parseProxyUrl'; diff --git a/desktop/node_modules/global-agent/src/utilities/isUrlMatchingNoProxy.js b/desktop/node_modules/global-agent/src/utilities/isUrlMatchingNoProxy.js new file mode 100644 index 0000000..f2de584 --- /dev/null +++ b/desktop/node_modules/global-agent/src/utilities/isUrlMatchingNoProxy.js @@ -0,0 +1,37 @@ +// @flow + +import { + parse as parseUrl, +} from 'url'; +import matcher from 'matcher'; +import { + UnexpectedStateError, +} from '../errors'; + +export default (subjectUrl: string, noProxy: string) => { + const subjectUrlTokens = parseUrl(subjectUrl); + + const rules = noProxy.split(/[\s,]+/); + + for (const rule of rules) { + const ruleMatch = rule + .replace(/^(?<leadingDot>\.)/, '*') + .match(/^(?<hostname>.+?)(?::(?<port>\d+))?$/); + + if (!ruleMatch || !ruleMatch.groups) { + throw new UnexpectedStateError('Invalid NO_PROXY pattern.'); + } + + if (!ruleMatch.groups.hostname) { + throw new UnexpectedStateError('NO_PROXY entry pattern must include hostname. Use * to match any hostname.'); + } + + const hostnameIsMatch = matcher.isMatch(subjectUrlTokens.hostname, ruleMatch.groups.hostname); + + if (hostnameIsMatch && (!ruleMatch.groups || !ruleMatch.groups.port || subjectUrlTokens.port && subjectUrlTokens.port === ruleMatch.groups.port)) { + return true; + } + } + + return false; +}; diff --git a/desktop/node_modules/global-agent/src/utilities/parseProxyUrl.js b/desktop/node_modules/global-agent/src/utilities/parseProxyUrl.js new file mode 100644 index 0000000..e2e9a6b --- /dev/null +++ b/desktop/node_modules/global-agent/src/utilities/parseProxyUrl.js @@ -0,0 +1,36 @@ +// @flow + +import { + parse as parseUrl, +} from 'url'; +import { + UnexpectedStateError, +} from '../errors'; + +export default (url: string) => { + const urlTokens = parseUrl(url); + + if (urlTokens.query !== null) { + throw new UnexpectedStateError('Unsupported `GLOBAL_AGENT.HTTP_PROXY` configuration value: URL must not have query.'); + } + + if (urlTokens.hash !== null) { + throw new UnexpectedStateError('Unsupported `GLOBAL_AGENT.HTTP_PROXY` configuration value: URL must not have hash.'); + } + + if (urlTokens.protocol !== 'http:') { + throw new UnexpectedStateError('Unsupported `GLOBAL_AGENT.HTTP_PROXY` configuration value: URL protocol must be "http:".'); + } + + let port = 80; + + if (urlTokens.port) { + port = Number.parseInt(urlTokens.port, 10); + } + + return { + authorization: urlTokens.auth || null, + hostname: urlTokens.hostname, + port, + }; +}; |