global-agent 4.1.2 → 4.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/Logger.d.ts +11 -0
  2. package/dist/Logger.js +56 -0
  3. package/dist/classes/Agent.d.ts +46 -0
  4. package/dist/classes/Agent.js +216 -0
  5. package/dist/classes/HttpProxyAgent.d.ts +7 -0
  6. package/dist/classes/HttpProxyAgent.js +20 -0
  7. package/dist/classes/HttpsProxyAgent.d.ts +7 -0
  8. package/dist/classes/HttpsProxyAgent.js +48 -0
  9. package/dist/classes/index.d.ts +3 -0
  10. package/dist/classes/index.js +12 -0
  11. package/dist/errors.d.ts +4 -0
  12. package/dist/errors.js +10 -0
  13. package/dist/factories/createGlobalProxyAgent.d.ts +7 -0
  14. package/dist/factories/createGlobalProxyAgent.js +131 -0
  15. package/dist/factories/createGlobalProxyAgent.test.d.ts +1 -0
  16. package/dist/factories/createGlobalProxyAgent.test.js +539 -0
  17. package/dist/factories/createProxyController.d.ts +7 -0
  18. package/dist/factories/createProxyController.js +38 -0
  19. package/dist/factories/createProxyController.test.d.ts +1 -0
  20. package/dist/factories/createProxyController.test.js +29 -0
  21. package/dist/factories/index.d.ts +2 -0
  22. package/dist/factories/index.js +10 -0
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.js +7 -0
  25. package/dist/routines/bootstrap.d.ts +3 -0
  26. package/dist/routines/bootstrap.js +20 -0
  27. package/dist/routines/index.d.ts +1 -0
  28. package/dist/routines/index.js +8 -0
  29. package/dist/types.d.ts +57 -0
  30. package/dist/types.js +2 -0
  31. package/dist/utilities/bindHttpMethod.d.ts +7 -0
  32. package/dist/utilities/bindHttpMethod.js +50 -0
  33. package/dist/utilities/index.d.ts +3 -0
  34. package/dist/utilities/index.js +12 -0
  35. package/dist/utilities/isUrlMatchingNoProxy.d.ts +2 -0
  36. package/dist/utilities/isUrlMatchingNoProxy.js +27 -0
  37. package/dist/utilities/isUrlMatchingNoProxy.test.d.ts +1 -0
  38. package/dist/utilities/isUrlMatchingNoProxy.test.js +61 -0
  39. package/dist/utilities/parseBoolean.d.ts +1 -0
  40. package/dist/utilities/parseBoolean.js +16 -0
  41. package/dist/utilities/parseProxyUrl.d.ts +6 -0
  42. package/dist/utilities/parseProxyUrl.js +31 -0
  43. package/dist/utilities/parseProxyUrl.test.d.ts +1 -0
  44. package/dist/utilities/parseProxyUrl.test.js +31 -0
  45. package/package.json +5 -2
  46. package/.babelrc +0 -23
  47. package/.editorconfig +0 -9
  48. package/.github/FUNDING.yml +0 -2
  49. package/.github/workflows/feature.yaml +0 -35
  50. package/.github/workflows/main.yaml +0 -50
  51. package/.gitignore +0 -12
  52. package/bootstrap.js +0 -1
  53. package/src/Logger.ts +0 -70
  54. package/src/classes/Agent.ts +0 -296
  55. package/src/classes/HttpProxyAgent.ts +0 -45
  56. package/src/classes/HttpsProxyAgent.ts +0 -83
  57. package/src/classes/index.ts +0 -9
  58. package/src/errors.ts +0 -9
  59. package/src/factories/createGlobalProxyAgent.test.ts +0 -761
  60. package/src/factories/createGlobalProxyAgent.ts +0 -187
  61. package/src/factories/createProxyController.test.ts +0 -38
  62. package/src/factories/createProxyController.ts +0 -51
  63. package/src/factories/index.ts +0 -6
  64. package/src/index.ts +0 -9
  65. package/src/routines/bootstrap.ts +0 -28
  66. package/src/routines/index.ts +0 -3
  67. package/src/types.ts +0 -70
  68. package/src/utilities/bindHttpMethod.ts +0 -53
  69. package/src/utilities/index.ts +0 -9
  70. package/src/utilities/isUrlMatchingNoProxy.test.ts +0 -77
  71. package/src/utilities/isUrlMatchingNoProxy.ts +0 -32
  72. package/src/utilities/parseBoolean.ts +0 -17
  73. package/src/utilities/parseProxyUrl.test.ts +0 -35
  74. package/src/utilities/parseProxyUrl.ts +0 -39
  75. package/tsconfig.json +0 -25
  76. package/vitest.config.ts +0 -11
@@ -1,187 +0,0 @@
1
- import http from 'http';
2
- import https from 'https';
3
- import semverGte from 'semver/functions/gte';
4
- import {
5
- logger,
6
- setLogger,
7
- } from '../Logger';
8
- import {
9
- HttpProxyAgent,
10
- HttpsProxyAgent,
11
- } from '../classes';
12
- import {
13
- UnexpectedStateError,
14
- } from '../errors';
15
- import type {
16
- ProxyAgentConfigurationInputType,
17
- ProxyAgentConfigurationType,
18
- } from '../types';
19
- import {
20
- bindHttpMethod,
21
- isUrlMatchingNoProxy,
22
- parseProxyUrl,
23
- } from '../utilities';
24
- import {
25
- parseBoolean,
26
- } from '../utilities/parseBoolean';
27
- import createProxyController from './createProxyController';
28
-
29
- const httpGet = http.get;
30
- const httpRequest = http.request;
31
- const httpsGet = https.get;
32
- const httpsRequest = https.request;
33
-
34
- const log = logger.child({
35
- namespace: 'createGlobalProxyAgent',
36
- });
37
-
38
- const defaultConfigurationInput = {
39
- environmentVariableNamespace: undefined,
40
- forceGlobalAgent: undefined,
41
- socketConnectionTimeout: 60_000,
42
- };
43
-
44
- const createConfiguration = (configurationInput: ProxyAgentConfigurationInputType): ProxyAgentConfigurationType => {
45
- // oxlint-disable-next-line node/no-process-env
46
- const environment = process.env;
47
-
48
- const defaultConfiguration = {
49
- environmentVariableNamespace: typeof environment.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE === 'string' ? environment.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE : 'GLOBAL_AGENT_',
50
- forceGlobalAgent: typeof environment.GLOBAL_AGENT_FORCE_GLOBAL_AGENT === 'string' ? parseBoolean(environment.GLOBAL_AGENT_FORCE_GLOBAL_AGENT) : true,
51
- socketConnectionTimeout: typeof environment.GLOBAL_AGENT_SOCKET_CONNECTION_TIMEOUT === 'string' ? Number.parseInt(environment.GLOBAL_AGENT_SOCKET_CONNECTION_TIMEOUT, 10) : defaultConfigurationInput.socketConnectionTimeout,
52
- };
53
-
54
- return {
55
- ...defaultConfiguration,
56
- ...Object.fromEntries(Object.entries(configurationInput).filter(([, v]) => v !== undefined)),
57
- };
58
- };
59
-
60
- export default (configurationInput: ProxyAgentConfigurationInputType = defaultConfigurationInput) => {
61
- const configuration = createConfiguration(configurationInput);
62
-
63
- if (configurationInput.logger) {
64
- setLogger(configurationInput.logger);
65
- }
66
-
67
- const proxyController = createProxyController();
68
-
69
- // oxlint-disable-next-line node/no-process-env
70
- proxyController.HTTP_PROXY = process.env[configuration.environmentVariableNamespace + 'HTTP_PROXY'] ?? null;
71
-
72
- // oxlint-disable-next-line node/no-process-env
73
- proxyController.HTTPS_PROXY = process.env[configuration.environmentVariableNamespace + 'HTTPS_PROXY'] ?? null;
74
-
75
- // oxlint-disable-next-line node/no-process-env
76
- proxyController.NO_PROXY = process.env[configuration.environmentVariableNamespace + 'NO_PROXY'] ?? null;
77
-
78
- log.info({
79
- configuration,
80
- state: proxyController,
81
- }, 'global agent has been initialized');
82
-
83
- const mustUrlUseProxy = (getProxy: () => string | null) => {
84
- return (url: string): boolean => {
85
- if (!getProxy()) {
86
- return false;
87
- }
88
-
89
- if (!proxyController.NO_PROXY) {
90
- return true;
91
- }
92
-
93
- return !isUrlMatchingNoProxy(url, proxyController.NO_PROXY);
94
- };
95
- };
96
-
97
- const getUrlProxy = (getProxy: () => string | null) => {
98
- return () => {
99
- const proxy = getProxy();
100
-
101
- if (!proxy) {
102
- throw new UnexpectedStateError('HTTP(S) proxy must be configured.');
103
- }
104
-
105
- return parseProxyUrl(proxy);
106
- };
107
- };
108
-
109
- const getHttpProxy = () => {
110
- return proxyController.HTTP_PROXY;
111
- };
112
-
113
- const BoundHttpProxyAgent = class extends HttpProxyAgent {
114
- public constructor () {
115
- super(
116
- () => {
117
- return Boolean(getHttpProxy());
118
- },
119
- mustUrlUseProxy(getHttpProxy),
120
- getUrlProxy(getHttpProxy),
121
- http.globalAgent,
122
- configuration.socketConnectionTimeout,
123
- configuration.ca,
124
- );
125
- }
126
- };
127
-
128
- const httpAgent = new BoundHttpProxyAgent();
129
-
130
- const getHttpsProxy = () => {
131
- return proxyController.HTTPS_PROXY ?? proxyController.HTTP_PROXY;
132
- };
133
-
134
- const BoundHttpsProxyAgent = class extends HttpsProxyAgent {
135
- public constructor () {
136
- super(
137
- () => {
138
- return Boolean(getHttpsProxy());
139
- },
140
- mustUrlUseProxy(getHttpsProxy),
141
- getUrlProxy(getHttpsProxy),
142
- https.globalAgent,
143
- configuration.socketConnectionTimeout,
144
- configuration.ca,
145
- );
146
- }
147
- };
148
-
149
- const httpsAgent = new BoundHttpsProxyAgent();
150
-
151
- // Overriding globalAgent was added in v11.7.
152
- // @see https://nodejs.org/uk/blog/release/v11.7.0/
153
- if (semverGte(process.version, 'v11.7.0')) {
154
- // @see https://github.com/facebook/flow/issues/7670
155
- // @ts-expect-error Node.js version compatibility
156
- http.globalAgent = httpAgent;
157
-
158
- // @ts-expect-error Node.js version compatibility
159
- https.globalAgent = httpsAgent;
160
- }
161
-
162
- // The reason this logic is used in addition to overriding http(s).globalAgent
163
- // is because there is no guarantee that we set http(s).globalAgent variable
164
- // before an instance of http(s).Agent has been already constructed by someone,
165
- // e.g. Stripe SDK creates instances of http(s).Agent at the top-level.
166
- // @see https://github.com/gajus/global-agent/pull/13
167
- //
168
- // We still want to override http(s).globalAgent when possible to enable logic
169
- // in `bindHttpMethod`.
170
- if (semverGte(process.version, 'v10.0.0')) {
171
- // @ts-expect-error seems like we are using wrong type for httpAgent
172
- http.get = bindHttpMethod(httpGet, httpAgent, configuration.forceGlobalAgent);
173
-
174
- // @ts-expect-error seems like we are using wrong type for httpAgent
175
- http.request = bindHttpMethod(httpRequest, httpAgent, configuration.forceGlobalAgent);
176
-
177
- // @ts-expect-error seems like we are using wrong type for httpAgent
178
- https.get = bindHttpMethod(httpsGet, httpsAgent, configuration.forceGlobalAgent);
179
-
180
- // @ts-expect-error seems like we are using wrong type for httpAgent
181
- https.request = bindHttpMethod(httpsRequest, httpsAgent, configuration.forceGlobalAgent);
182
- } else {
183
- log.warn('attempt to initialize global-agent in unsupported Node.js version was ignored');
184
- }
185
-
186
- return proxyController;
187
- };
@@ -1,38 +0,0 @@
1
- import {
2
- expect,
3
- test,
4
- } from 'vitest';
5
- import createProxyController from './createProxyController';
6
-
7
- test('sets HTTP_PROXY', () => {
8
- const globalAgentGlobal = createProxyController();
9
-
10
- globalAgentGlobal.HTTP_PROXY = 'http://127.0.0.1';
11
-
12
- expect(globalAgentGlobal.HTTP_PROXY).toBe('http://127.0.0.1');
13
- });
14
-
15
- test('sets HTTPS_PROXY', () => {
16
- const globalAgentGlobal = createProxyController();
17
-
18
- globalAgentGlobal.HTTPS_PROXY = 'http://127.0.0.1';
19
-
20
- expect(globalAgentGlobal.HTTPS_PROXY).toBe('http://127.0.0.1');
21
- });
22
-
23
- test('sets NO_PROXY', () => {
24
- const globalAgentGlobal = createProxyController();
25
-
26
- globalAgentGlobal.NO_PROXY = '*';
27
-
28
- expect(globalAgentGlobal.NO_PROXY).toBe('*');
29
- });
30
-
31
- test('throws an error if unknown property is set', () => {
32
- const globalAgentGlobal = createProxyController();
33
-
34
- expect(() => {
35
- // @ts-expect-error expected unknown property.
36
- globalAgentGlobal.FOO = 'BAR';
37
- }).toThrow('Cannot set an unmapped property "FOO".');
38
- });
@@ -1,51 +0,0 @@
1
- import {
2
- logger,
3
- } from '../Logger';
4
-
5
- type ProxyController = {
6
- HTTP_PROXY: string | null,
7
- HTTPS_PROXY: string | null,
8
- NO_PROXY: string | null,
9
- };
10
-
11
- const log = logger.child({
12
- namespace: 'createProxyController',
13
- });
14
-
15
- const KNOWN_PROPERTY_NAMES = [
16
- 'HTTP_PROXY',
17
- 'HTTPS_PROXY',
18
- 'NO_PROXY',
19
- ];
20
-
21
- export default (): ProxyController => {
22
- // oxlint-disable-next-line fp/no-proxy
23
- return new Proxy({
24
- HTTP_PROXY: null,
25
- HTTPS_PROXY: null,
26
- NO_PROXY: null,
27
- }, {
28
- set: (subject, name, value) => {
29
- if (typeof name !== 'string') {
30
- throw new TypeError('Unexpected object member.');
31
- }
32
-
33
- if (!KNOWN_PROPERTY_NAMES.includes(name)) {
34
- throw new Error('Cannot set an unmapped property "' + name + '".');
35
- }
36
-
37
- // @ts-expect-error string cannot be used to index an object
38
- subject[name] = value;
39
-
40
- log.info({
41
- change: {
42
- name,
43
- value,
44
- },
45
- newConfiguration: subject,
46
- }, 'configuration changed');
47
-
48
- return true;
49
- },
50
- });
51
- };
@@ -1,6 +0,0 @@
1
- export {
2
- default as createGlobalProxyAgent,
3
- } from './createGlobalProxyAgent';
4
- export {
5
- default as createProxyController,
6
- } from './createProxyController';
package/src/index.ts DELETED
@@ -1,9 +0,0 @@
1
- export {
2
- bootstrap,
3
- } from './routines';
4
- export {
5
- createGlobalProxyAgent,
6
- } from './factories';
7
- export type {
8
- Logger,
9
- } from './Logger';
@@ -1,28 +0,0 @@
1
- import createGlobalThis from 'globalthis';
2
- import {
3
- logger,
4
- } from '../Logger';
5
- import {
6
- createGlobalProxyAgent,
7
- } from '../factories';
8
- import type {
9
- ProxyAgentConfigurationInputType,
10
- } from '../types';
11
-
12
- const globalThis: any = createGlobalThis();
13
-
14
- const log = logger.child({
15
- namespace: 'bootstrap',
16
- });
17
-
18
- export default (configurationInput?: ProxyAgentConfigurationInputType): boolean => {
19
- if (globalThis.GLOBAL_AGENT) {
20
- log.warn('found globalThis.GLOBAL_AGENT; second attempt to bootstrap global-agent was ignored');
21
-
22
- return false;
23
- }
24
-
25
- globalThis.GLOBAL_AGENT = createGlobalProxyAgent(configurationInput);
26
-
27
- return true;
28
- };
@@ -1,3 +0,0 @@
1
- export {
2
- default as bootstrap,
3
- } from './bootstrap';
package/src/types.ts DELETED
@@ -1,70 +0,0 @@
1
- import type {
2
- Agent as HttpAgent,
3
- } from 'http';
4
- import type {
5
- Agent as HttpsAgent,
6
- } from 'https';
7
- import type {
8
- Socket,
9
- } from 'net';
10
- import type {
11
- TLSSocket,
12
- } from 'tls';
13
- import type {
14
- Logger,
15
- } from './Logger';
16
-
17
- export type ProxyConfigurationType = {
18
- authorization: string | null,
19
- hostname: string,
20
- port: number,
21
- };
22
-
23
- export type TlsConfigurationType = {
24
- ca?: string[] | string,
25
- cert?: string,
26
- ciphers?: string,
27
- clientCertEngine?: string,
28
- crl?: string,
29
- dhparam?: string,
30
- ecdhCurve?: string,
31
- honorCipherOrder?: boolean,
32
- key?: string,
33
- passphrase?: string,
34
- pfx?: string,
35
- rejectUnauthorized?: boolean,
36
- secureOptions?: number,
37
- secureProtocol?: string,
38
- servername?: string,
39
- sessionIdContext?: string,
40
- };
41
-
42
- export type ConnectionConfigurationType = {
43
- host: string,
44
- port: number,
45
- tls?: TlsConfigurationType,
46
- proxy: ProxyConfigurationType,
47
- };
48
-
49
- export type ConnectionCallbackType = (error: Error | null, socket?: Socket | TLSSocket) => void;
50
-
51
- export type AgentType = HttpAgent | HttpsAgent;
52
- export type IsProxyConfiguredMethodType = () => boolean;
53
- export type MustUrlUseProxyMethodType = (url: string) => boolean;
54
- export type GetUrlProxyMethodType = (url: string) => ProxyConfigurationType;
55
- export type ProtocolType = 'http:' | 'https:';
56
-
57
- export type ProxyAgentConfigurationInputType = {
58
- environmentVariableNamespace?: string,
59
- forceGlobalAgent?: boolean,
60
- socketConnectionTimeout?: number,
61
- ca?: string[] | string,
62
- logger?: Logger,
63
- };
64
-
65
- export type ProxyAgentConfigurationType = {
66
- environmentVariableNamespace: string,
67
- forceGlobalAgent: boolean,
68
- socketConnectionTimeout: number,
69
- ca?: string[] | string,
70
- };
@@ -1,53 +0,0 @@
1
- import http from 'http';
2
- import https from 'https';
3
-
4
- type AgentType = http.Agent | https.Agent;
5
-
6
- export default (
7
- originalMethod: Function,
8
- agent: AgentType,
9
- forceGlobalAgent: boolean,
10
- ) => {
11
- return (...args: any[]) => {
12
- let url;
13
- let options;
14
- let callback;
15
-
16
- if (typeof args[0] === 'string' || args[0] instanceof URL) {
17
- url = args[0];
18
-
19
- if (typeof args[1] === 'function') {
20
- options = {};
21
- callback = args[1];
22
- } else {
23
- options = {
24
- ...args[1],
25
- };
26
- callback = args[2];
27
- }
28
- } else {
29
- options = {
30
- ...args[0],
31
- };
32
- callback = args[1];
33
- }
34
-
35
- if (forceGlobalAgent) {
36
- options.agent = agent;
37
- } else {
38
- if (!options.agent) {
39
- options.agent = agent;
40
- }
41
-
42
- if (options.agent === http.globalAgent || options.agent === https.globalAgent) {
43
- options.agent = agent;
44
- }
45
- }
46
-
47
- if (url) {
48
- return originalMethod(url, options, callback);
49
- } else {
50
- return originalMethod(options, callback);
51
- }
52
- };
53
- };
@@ -1,9 +0,0 @@
1
- export {
2
- default as bindHttpMethod,
3
- } from './bindHttpMethod';
4
- export {
5
- default as isUrlMatchingNoProxy,
6
- } from './isUrlMatchingNoProxy';
7
- export {
8
- default as parseProxyUrl,
9
- } from './parseProxyUrl';
@@ -1,77 +0,0 @@
1
- import {
2
- expect,
3
- test,
4
- } from 'vitest';
5
- import isUrlMatchingNoProxy from './isUrlMatchingNoProxy';
6
-
7
- test('returns `true` if hosts match', () => {
8
- expect(isUrlMatchingNoProxy('http://foo.com/', 'foo.com')).toBe(true);
9
- });
10
-
11
- test('returns `true` if hosts match (IP)', () => {
12
- expect(isUrlMatchingNoProxy('http://127.0.0.1/', '127.0.0.1')).toBe(true);
13
- });
14
-
15
- test('returns `true` if hosts match (using asterisk wildcard)', () => {
16
- expect(isUrlMatchingNoProxy('http://bar.foo.com/', '*.foo.com')).toBe(true);
17
- });
18
-
19
- test('returns `true` if domain matches (using dot wildcard)', () => {
20
- expect(isUrlMatchingNoProxy('http://foo.com/', '.foo.com')).toBe(true);
21
- });
22
-
23
- test('returns `true` if subdomain matches (using dot wildcard)', () => {
24
- expect(isUrlMatchingNoProxy('http://bar.foo.com/', '.foo.com')).toBe(true);
25
- });
26
-
27
- test('returns `true` if hosts match (*) and ports match', () => {
28
- expect(isUrlMatchingNoProxy('http://foo.com:8080/', '*:8080')).toBe(true);
29
- });
30
-
31
- test('returns `true` if hosts and ports match', () => {
32
- expect(isUrlMatchingNoProxy('http://foo.com:8080/', 'foo.com:8080')).toBe(true);
33
- });
34
-
35
- test('returns `true` if hosts match and NO_PROXY does not define port', () => {
36
- expect(isUrlMatchingNoProxy('http://foo.com:8080/', 'foo.com')).toBe(true);
37
- });
38
-
39
- test('returns `true` if hosts (IP) and ports match', () => {
40
- expect(isUrlMatchingNoProxy('http://127.0.0.1:8080/', '127.0.0.1:8080')).toBe(true);
41
- });
42
-
43
- test('returns `false` if hosts match and ports do not match (diffferent port)', () => {
44
- expect(isUrlMatchingNoProxy('http://foo.com:8080/', 'foo.com:8000')).toBe(false);
45
- });
46
-
47
- test('returns `false` if hosts match and ports do not match (port not present subject)', () => {
48
- expect(isUrlMatchingNoProxy('http://foo.com/', 'foo.com:8000')).toBe(false);
49
- });
50
-
51
- test('returns `true` if hosts match and ports do not match (port not present NO_PROXY)', () => {
52
- expect(isUrlMatchingNoProxy('http://foo.com:8000/', 'foo.com')).toBe(true);
53
- });
54
-
55
- test('returns `true` if hosts match in one of multiple rules separated with a comma', () => {
56
- expect(isUrlMatchingNoProxy('http://foo.com/', 'bar.org,foo.com,baz.io')).toBe(true);
57
- });
58
-
59
- test('returns `true` if hosts match in one of multiple rules separated with a comma and a space', () => {
60
- expect(isUrlMatchingNoProxy('http://foo.com/', 'bar.org, foo.com, baz.io')).toBe(true);
61
- });
62
-
63
- test('returns `true` if hosts match in one of multiple rules separated with a space', () => {
64
- expect(isUrlMatchingNoProxy('http://foo.com/', 'bar.org foo.com baz.io')).toBe(true);
65
- });
66
-
67
- test('handles trailing newline in NO_PROXY', () => {
68
- expect(isUrlMatchingNoProxy('http://foo.com/', 'foo.com\n')).toBe(true);
69
- });
70
-
71
- test('handles trailing whitespace in NO_PROXY', () => {
72
- expect(isUrlMatchingNoProxy('http://foo.com/', 'foo.com ')).toBe(true);
73
- });
74
-
75
- test('handles leading whitespace in NO_PROXY', () => {
76
- expect(isUrlMatchingNoProxy('http://foo.com/', ' foo.com')).toBe(true);
77
- });
@@ -1,32 +0,0 @@
1
- import matcher from 'matcher';
2
- import {
3
- UnexpectedStateError,
4
- } from '../errors';
5
-
6
- export default (subjectUrl: string, noProxy: string) => {
7
- const subjectUrlTokens = new URL(subjectUrl);
8
-
9
- const rules = noProxy.split(/[\s,]+/).filter(Boolean);
10
-
11
- for (const rule of rules) {
12
- const ruleMatch = rule
13
- .replace(/^(?<leadingDot>\.)/, '*')
14
- .match(/^(?<hostname>.+?)(?::(?<port>\d+))?$/);
15
-
16
- if (!ruleMatch || !ruleMatch.groups) {
17
- throw new UnexpectedStateError('Invalid NO_PROXY pattern.');
18
- }
19
-
20
- if (!ruleMatch.groups.hostname) {
21
- throw new UnexpectedStateError('NO_PROXY entry pattern must include hostname. Use * to match any hostname.');
22
- }
23
-
24
- const hostnameIsMatch = matcher.isMatch(subjectUrlTokens.hostname, ruleMatch.groups.hostname);
25
-
26
- if (hostnameIsMatch && (!ruleMatch.groups || !ruleMatch.groups.port || subjectUrlTokens.port && subjectUrlTokens.port === ruleMatch.groups.port)) {
27
- return true;
28
- }
29
- }
30
-
31
- return false;
32
- };
@@ -1,17 +0,0 @@
1
- export const parseBoolean = function (value: any): boolean {
2
- switch (Object.prototype.toString.call(value)) {
3
- case '[object String]':
4
- return ['true', 't', 'yes', 'y', 'on', '1'].includes(
5
- value.trim().toLowerCase(),
6
- );
7
-
8
- case '[object Number]':
9
- return value.valueOf() === 1;
10
-
11
- case '[object Boolean]':
12
- return value.valueOf();
13
-
14
- default:
15
- return false;
16
- }
17
- };
@@ -1,35 +0,0 @@
1
- import {
2
- expect,
3
- test,
4
- } from 'vitest';
5
- import parseProxyUrl from './parseProxyUrl';
6
-
7
- test('extracts hostname', () => {
8
- expect(parseProxyUrl('http://0.0.0.0').hostname).toBe('0.0.0.0');
9
- });
10
-
11
- test('extracts port', () => {
12
- expect(parseProxyUrl('http://0.0.0.0:3000').port).toBe(3_000);
13
- });
14
-
15
- test('extracts authorization', () => {
16
- expect(parseProxyUrl('http://foo:bar@0.0.0.0').authorization).toBe('foo:bar');
17
- });
18
-
19
- test('throws an error if protocol is not "http:"', () => {
20
- expect(() => {
21
- parseProxyUrl('https://0.0.0.0:3000');
22
- }).toThrow('Unsupported `GLOBAL_AGENT.HTTP_PROXY` configuration value: URL protocol must be "http:".');
23
- });
24
-
25
- test('throws an error if query is present', () => {
26
- expect(() => {
27
- parseProxyUrl('http://0.0.0.0:3000/?foo=bar');
28
- }).toThrow('Unsupported `GLOBAL_AGENT.HTTP_PROXY` configuration value: URL must not have query.');
29
- });
30
-
31
- test('throws an error if hash is present', () => {
32
- expect(() => {
33
- parseProxyUrl('http://0.0.0.0:3000/#foo');
34
- }).toThrow('Unsupported `GLOBAL_AGENT.HTTP_PROXY` configuration value: URL must not have hash.');
35
- });
@@ -1,39 +0,0 @@
1
- import {
2
- UnexpectedStateError,
3
- } from '../errors';
4
-
5
- export default (url: string) => {
6
- const urlTokens = new URL(url);
7
-
8
- if (urlTokens.search !== '') {
9
- throw new UnexpectedStateError('Unsupported `GLOBAL_AGENT.HTTP_PROXY` configuration value: URL must not have query.');
10
- }
11
-
12
- if (urlTokens.hash !== '') {
13
- throw new UnexpectedStateError('Unsupported `GLOBAL_AGENT.HTTP_PROXY` configuration value: URL must not have hash.');
14
- }
15
-
16
- if (urlTokens.protocol !== 'http:') {
17
- throw new UnexpectedStateError('Unsupported `GLOBAL_AGENT.HTTP_PROXY` configuration value: URL protocol must be "http:".');
18
- }
19
-
20
- let port = 80;
21
-
22
- if (urlTokens.port) {
23
- port = Number.parseInt(urlTokens.port, 10);
24
- }
25
-
26
- let authorization = null;
27
-
28
- if (urlTokens.username && urlTokens.password) {
29
- authorization = urlTokens.username + ':' + urlTokens.password;
30
- } else if (urlTokens.username) {
31
- authorization = urlTokens.username;
32
- }
33
-
34
- return {
35
- authorization,
36
- hostname: urlTokens.hostname,
37
- port,
38
- };
39
- };