global-agent 4.1.1 → 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.
- package/dist/Logger.d.ts +11 -0
- package/dist/Logger.js +56 -0
- package/dist/classes/Agent.d.ts +46 -0
- package/dist/classes/Agent.js +216 -0
- package/dist/classes/HttpProxyAgent.d.ts +7 -0
- package/dist/classes/HttpProxyAgent.js +20 -0
- package/dist/classes/HttpsProxyAgent.d.ts +7 -0
- package/dist/classes/HttpsProxyAgent.js +48 -0
- package/dist/classes/index.d.ts +3 -0
- package/dist/classes/index.js +12 -0
- package/dist/errors.d.ts +4 -0
- package/dist/errors.js +10 -0
- package/dist/factories/createGlobalProxyAgent.d.ts +7 -0
- package/dist/factories/createGlobalProxyAgent.js +131 -0
- package/dist/factories/createGlobalProxyAgent.test.d.ts +1 -0
- package/dist/factories/createGlobalProxyAgent.test.js +539 -0
- package/dist/factories/createProxyController.d.ts +7 -0
- package/dist/factories/createProxyController.js +38 -0
- package/dist/factories/createProxyController.test.d.ts +1 -0
- package/dist/factories/createProxyController.test.js +29 -0
- package/dist/factories/index.d.ts +2 -0
- package/dist/factories/index.js +10 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +7 -0
- package/dist/routines/bootstrap.d.ts +3 -0
- package/dist/routines/bootstrap.js +20 -0
- package/dist/routines/index.d.ts +1 -0
- package/dist/routines/index.js +8 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.js +2 -0
- package/dist/utilities/bindHttpMethod.d.ts +7 -0
- package/dist/utilities/bindHttpMethod.js +50 -0
- package/dist/utilities/index.d.ts +3 -0
- package/dist/utilities/index.js +12 -0
- package/dist/utilities/isUrlMatchingNoProxy.d.ts +2 -0
- package/dist/utilities/isUrlMatchingNoProxy.js +27 -0
- package/dist/utilities/isUrlMatchingNoProxy.test.d.ts +1 -0
- package/dist/utilities/isUrlMatchingNoProxy.test.js +61 -0
- package/dist/utilities/parseBoolean.d.ts +1 -0
- package/dist/utilities/parseBoolean.js +16 -0
- package/dist/utilities/parseProxyUrl.d.ts +6 -0
- package/dist/utilities/parseProxyUrl.js +31 -0
- package/dist/utilities/parseProxyUrl.test.d.ts +1 -0
- package/dist/utilities/parseProxyUrl.test.js +31 -0
- package/package.json +5 -4
- package/.babelrc +0 -23
- package/.editorconfig +0 -9
- package/.github/FUNDING.yml +0 -2
- package/.github/workflows/feature.yaml +0 -35
- package/.github/workflows/main.yaml +0 -50
- package/.gitignore +0 -12
- package/bootstrap.js +0 -1
- package/src/Logger.ts +0 -70
- package/src/classes/Agent.ts +0 -296
- package/src/classes/HttpProxyAgent.ts +0 -45
- package/src/classes/HttpsProxyAgent.ts +0 -83
- package/src/classes/index.ts +0 -9
- package/src/errors.ts +0 -11
- package/src/factories/createGlobalProxyAgent.test.ts +0 -761
- package/src/factories/createGlobalProxyAgent.ts +0 -190
- package/src/factories/createProxyController.test.ts +0 -38
- package/src/factories/createProxyController.ts +0 -51
- package/src/factories/index.ts +0 -6
- package/src/index.ts +0 -9
- package/src/routines/bootstrap.ts +0 -28
- package/src/routines/index.ts +0 -3
- package/src/types.ts +0 -70
- package/src/utilities/bindHttpMethod.ts +0 -53
- package/src/utilities/index.ts +0 -9
- package/src/utilities/isUrlMatchingNoProxy.test.ts +0 -77
- package/src/utilities/isUrlMatchingNoProxy.ts +0 -32
- package/src/utilities/parseBoolean.ts +0 -17
- package/src/utilities/parseProxyUrl.test.ts +0 -35
- package/src/utilities/parseProxyUrl.ts +0 -39
- package/tsconfig.json +0 -25
- package/vitest.config.ts +0 -11
package/dist/Logger.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type LogMethod = (context: object | string, message?: string) => void;
|
|
2
|
+
export type Logger = {
|
|
3
|
+
child: (context: object) => Logger;
|
|
4
|
+
debug: LogMethod;
|
|
5
|
+
error: LogMethod;
|
|
6
|
+
info: LogMethod;
|
|
7
|
+
trace: LogMethod;
|
|
8
|
+
warn: LogMethod;
|
|
9
|
+
};
|
|
10
|
+
export declare const setLogger: (newLogger: Logger) => void;
|
|
11
|
+
export declare const logger: Logger;
|
package/dist/Logger.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = exports.setLogger = void 0;
|
|
4
|
+
// oxlint-disable-next-line @typescript-eslint/no-empty-function
|
|
5
|
+
const noop = () => { };
|
|
6
|
+
const createNoopLogger = () => {
|
|
7
|
+
return {
|
|
8
|
+
child: () => {
|
|
9
|
+
return createNoopLogger();
|
|
10
|
+
},
|
|
11
|
+
debug: noop,
|
|
12
|
+
error: noop,
|
|
13
|
+
info: noop,
|
|
14
|
+
trace: noop,
|
|
15
|
+
warn: noop,
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
let currentLogger = createNoopLogger();
|
|
19
|
+
const setLogger = (newLogger) => {
|
|
20
|
+
currentLogger = newLogger;
|
|
21
|
+
};
|
|
22
|
+
exports.setLogger = setLogger;
|
|
23
|
+
const createDelegatingLogger = (getContext) => {
|
|
24
|
+
const getLogger = () => {
|
|
25
|
+
let targetLogger = currentLogger;
|
|
26
|
+
for (const [key, value] of Object.entries(getContext())) {
|
|
27
|
+
targetLogger = targetLogger.child({ [key]: value });
|
|
28
|
+
}
|
|
29
|
+
return targetLogger;
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
child: (context) => {
|
|
33
|
+
return createDelegatingLogger(() => {
|
|
34
|
+
return { ...getContext(), ...context };
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
debug: (context, message) => {
|
|
38
|
+
getLogger().debug(context, message);
|
|
39
|
+
},
|
|
40
|
+
error: (context, message) => {
|
|
41
|
+
getLogger().error(context, message);
|
|
42
|
+
},
|
|
43
|
+
info: (context, message) => {
|
|
44
|
+
getLogger().info(context, message);
|
|
45
|
+
},
|
|
46
|
+
trace: (context, message) => {
|
|
47
|
+
getLogger().trace(context, message);
|
|
48
|
+
},
|
|
49
|
+
warn: (context, message) => {
|
|
50
|
+
getLogger().warn(context, message);
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
exports.logger = createDelegatingLogger(() => {
|
|
55
|
+
return { package: 'global-agent' };
|
|
56
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import type * as http from 'http';
|
|
4
|
+
import type * as https from 'https';
|
|
5
|
+
import type { AgentType, ConnectionCallbackType, ConnectionConfigurationType, GetUrlProxyMethodType, IsProxyConfiguredMethodType, MustUrlUseProxyMethodType, ProtocolType } from '../types';
|
|
6
|
+
type AgentRequestOptions = {
|
|
7
|
+
host?: string;
|
|
8
|
+
path?: string;
|
|
9
|
+
port: number;
|
|
10
|
+
};
|
|
11
|
+
type HttpRequestOptions = AgentRequestOptions & Omit<http.RequestOptions, keyof AgentRequestOptions> & {
|
|
12
|
+
secureEndpoint: false;
|
|
13
|
+
};
|
|
14
|
+
type HttpsRequestOptions = AgentRequestOptions & Omit<https.RequestOptions, keyof AgentRequestOptions> & {
|
|
15
|
+
secureEndpoint: true;
|
|
16
|
+
};
|
|
17
|
+
type RequestOptions = HttpRequestOptions | HttpsRequestOptions;
|
|
18
|
+
declare abstract class Agent {
|
|
19
|
+
defaultPort: number;
|
|
20
|
+
protocol: ProtocolType;
|
|
21
|
+
fallbackAgent: AgentType;
|
|
22
|
+
isProxyConfigured: IsProxyConfiguredMethodType;
|
|
23
|
+
mustUrlUseProxy: MustUrlUseProxyMethodType;
|
|
24
|
+
getUrlProxy: GetUrlProxyMethodType;
|
|
25
|
+
socketConnectionTimeout: number;
|
|
26
|
+
ca: string[] | string | undefined;
|
|
27
|
+
constructor(isProxyConfigured: IsProxyConfiguredMethodType, mustUrlUseProxy: MustUrlUseProxyMethodType, getUrlProxy: GetUrlProxyMethodType, fallbackAgent: AgentType, socketConnectionTimeout: number, ca: string[] | string | undefined);
|
|
28
|
+
/**
|
|
29
|
+
* This method can be used to append new ca certificates to existing ca certificates
|
|
30
|
+
*
|
|
31
|
+
* @param {string[] | string} ca a ca certificate or an array of ca certificates
|
|
32
|
+
*/
|
|
33
|
+
addCACertificates(ca: string[] | string): void;
|
|
34
|
+
/**
|
|
35
|
+
* This method clears existing CA Certificates.
|
|
36
|
+
* It sets ca to undefined
|
|
37
|
+
*/
|
|
38
|
+
clearCACertificates(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Evaluate value for tls reject unauthorized variable
|
|
41
|
+
*/
|
|
42
|
+
getRejectUnauthorized(): boolean;
|
|
43
|
+
abstract createConnection(configuration: ConnectionConfigurationType, callback: ConnectionCallbackType): void;
|
|
44
|
+
addRequest(request: http.ClientRequest, configuration: RequestOptions): void;
|
|
45
|
+
}
|
|
46
|
+
export default Agent;
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const net_1 = __importDefault(require("net"));
|
|
7
|
+
const serialize_error_1 = require("serialize-error");
|
|
8
|
+
const Logger_1 = require("../Logger");
|
|
9
|
+
const log = Logger_1.logger.child({
|
|
10
|
+
namespace: 'Agent',
|
|
11
|
+
});
|
|
12
|
+
let requestId = 0;
|
|
13
|
+
class Agent {
|
|
14
|
+
constructor(isProxyConfigured, mustUrlUseProxy, getUrlProxy, fallbackAgent, socketConnectionTimeout, ca) {
|
|
15
|
+
this.fallbackAgent = fallbackAgent;
|
|
16
|
+
this.isProxyConfigured = isProxyConfigured;
|
|
17
|
+
this.mustUrlUseProxy = mustUrlUseProxy;
|
|
18
|
+
this.getUrlProxy = getUrlProxy;
|
|
19
|
+
this.socketConnectionTimeout = socketConnectionTimeout;
|
|
20
|
+
this.ca = ca;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* This method can be used to append new ca certificates to existing ca certificates
|
|
24
|
+
*
|
|
25
|
+
* @param {string[] | string} ca a ca certificate or an array of ca certificates
|
|
26
|
+
*/
|
|
27
|
+
addCACertificates(ca) {
|
|
28
|
+
if (!ca) {
|
|
29
|
+
log.error('Invalid input ca certificate');
|
|
30
|
+
}
|
|
31
|
+
else if (this.ca) {
|
|
32
|
+
if (typeof ca === typeof this.ca) {
|
|
33
|
+
// concat valid ca certificates with the existing certificates,
|
|
34
|
+
if (typeof this.ca === 'string') {
|
|
35
|
+
this.ca = this.ca.concat(ca);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
this.ca = this.ca.concat(ca);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
log.error('Input ca certificate type mismatched with existing ca certificate type');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.ca = ca;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* This method clears existing CA Certificates.
|
|
51
|
+
* It sets ca to undefined
|
|
52
|
+
*/
|
|
53
|
+
clearCACertificates() {
|
|
54
|
+
this.ca = undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Evaluate value for tls reject unauthorized variable
|
|
58
|
+
*/
|
|
59
|
+
getRejectUnauthorized() {
|
|
60
|
+
// oxlint-disable-next-line node/no-process-env
|
|
61
|
+
const rejectUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED;
|
|
62
|
+
let returnValue = true;
|
|
63
|
+
if (typeof rejectUnauthorized === 'boolean') {
|
|
64
|
+
returnValue = rejectUnauthorized;
|
|
65
|
+
}
|
|
66
|
+
else if (typeof rejectUnauthorized === 'number') {
|
|
67
|
+
returnValue = rejectUnauthorized === 1;
|
|
68
|
+
}
|
|
69
|
+
else if (typeof rejectUnauthorized === 'string') {
|
|
70
|
+
returnValue = ['true', 't', 'yes', 'y', 'on', '1'].includes(rejectUnauthorized.trim().toLowerCase());
|
|
71
|
+
}
|
|
72
|
+
return returnValue;
|
|
73
|
+
}
|
|
74
|
+
addRequest(request, configuration) {
|
|
75
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
76
|
+
let requestUrl;
|
|
77
|
+
// It is possible that addRequest was constructed for a proxied request already, e.g.
|
|
78
|
+
// "request" package does this when it detects that a proxy should be used
|
|
79
|
+
// https://github.com/request/request/blob/212570b6971a732b8dd9f3c73354bcdda158a737/request.js#L402
|
|
80
|
+
// https://gist.github.com/gajus/e2074cd3b747864ffeaabbd530d30218
|
|
81
|
+
if ((_a = request.path.startsWith('http://')) !== null && _a !== void 0 ? _a : request.path.startsWith('https://')) {
|
|
82
|
+
requestUrl = request.path;
|
|
83
|
+
}
|
|
84
|
+
else if (request.method === 'CONNECT') {
|
|
85
|
+
requestUrl = 'https://' + request.path;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
requestUrl = this.protocol + '//' + ((_b = configuration.hostname) !== null && _b !== void 0 ? _b : configuration.host) + (configuration.port === 80 || configuration.port === 443 ? '' : ':' + configuration.port) + request.path;
|
|
89
|
+
}
|
|
90
|
+
// If a request should go to a local socket, proxying it through an HTTP
|
|
91
|
+
// server does not make sense as the information about the target socket
|
|
92
|
+
// will be lost and the proxy won't be able to correctly handle the request.
|
|
93
|
+
if (configuration.socketPath) {
|
|
94
|
+
log.trace({
|
|
95
|
+
destination: configuration.socketPath,
|
|
96
|
+
}, 'not proxying request; destination is a socket');
|
|
97
|
+
// @ts-expect-error seems like we are using wrong type for fallbackAgent.
|
|
98
|
+
this.fallbackAgent.addRequest(request, configuration);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (!this.isProxyConfigured()) {
|
|
102
|
+
log.trace({
|
|
103
|
+
destination: requestUrl,
|
|
104
|
+
}, 'not proxying request; GLOBAL_AGENT.HTTP_PROXY is not configured');
|
|
105
|
+
// @ts-expect-error seems like we are using wrong type for fallbackAgent.
|
|
106
|
+
this.fallbackAgent.addRequest(request, configuration);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (!this.mustUrlUseProxy(requestUrl)) {
|
|
110
|
+
log.trace({
|
|
111
|
+
destination: requestUrl,
|
|
112
|
+
}, 'not proxying request; url matches GLOBAL_AGENT.NO_PROXY');
|
|
113
|
+
// @ts-expect-error seems like we are using wrong type for fallbackAgent.
|
|
114
|
+
this.fallbackAgent.addRequest(request, configuration);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const currentRequestId = requestId++;
|
|
118
|
+
const proxy = this.getUrlProxy(requestUrl);
|
|
119
|
+
if (this.protocol === 'http:') {
|
|
120
|
+
request.path = requestUrl;
|
|
121
|
+
if (proxy.authorization) {
|
|
122
|
+
request.setHeader('proxy-authorization', 'Basic ' + Buffer.from(proxy.authorization).toString('base64'));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
log.trace({
|
|
126
|
+
destination: requestUrl,
|
|
127
|
+
proxy: 'http://' + proxy.hostname + ':' + proxy.port,
|
|
128
|
+
requestId: currentRequestId,
|
|
129
|
+
}, 'proxying request');
|
|
130
|
+
request.on('error', (error) => {
|
|
131
|
+
log.error({
|
|
132
|
+
error: (0, serialize_error_1.serializeError)(error),
|
|
133
|
+
}, 'request error');
|
|
134
|
+
});
|
|
135
|
+
request.once('response', (response) => {
|
|
136
|
+
log.trace({
|
|
137
|
+
headers: response.headers,
|
|
138
|
+
requestId: currentRequestId,
|
|
139
|
+
statusCode: response.statusCode,
|
|
140
|
+
}, 'proxying response');
|
|
141
|
+
});
|
|
142
|
+
request.shouldKeepAlive = false;
|
|
143
|
+
const connectionConfiguration = {
|
|
144
|
+
host: (_d = (_c = configuration.hostname) !== null && _c !== void 0 ? _c : configuration.host) !== null && _d !== void 0 ? _d : '',
|
|
145
|
+
port: (_e = configuration.port) !== null && _e !== void 0 ? _e : 80,
|
|
146
|
+
proxy,
|
|
147
|
+
tls: {},
|
|
148
|
+
};
|
|
149
|
+
// add optional tls options for https requests.
|
|
150
|
+
// @see https://nodejs.org/docs/latest-v12.x/api/https.html#https_https_request_url_options_callback :
|
|
151
|
+
// > The following additional options from tls.connect()
|
|
152
|
+
// > - https://nodejs.org/docs/latest-v12.x/api/tls.html#tls_tls_connect_options_callback -
|
|
153
|
+
// > are also accepted:
|
|
154
|
+
// > ca, cert, ciphers, clientCertEngine, crl, dhparam, ecdhCurve, honorCipherOrder,
|
|
155
|
+
// > key, passphrase, pfx, rejectUnauthorized, secureOptions, secureProtocol, servername, sessionIdContext.
|
|
156
|
+
if (configuration.secureEndpoint) {
|
|
157
|
+
// Determine servername - Node.js doesn't allow IP addresses as servername
|
|
158
|
+
const host = (_f = configuration.servername) !== null && _f !== void 0 ? _f : connectionConfiguration.host;
|
|
159
|
+
const servername = net_1.default.isIP(host) ? undefined : host;
|
|
160
|
+
connectionConfiguration.tls = {
|
|
161
|
+
ca: (_g = configuration.ca) !== null && _g !== void 0 ? _g : this.ca,
|
|
162
|
+
cert: configuration.cert,
|
|
163
|
+
ciphers: configuration.ciphers,
|
|
164
|
+
clientCertEngine: configuration.clientCertEngine,
|
|
165
|
+
crl: configuration.crl,
|
|
166
|
+
dhparam: configuration.dhparam,
|
|
167
|
+
ecdhCurve: configuration.ecdhCurve,
|
|
168
|
+
honorCipherOrder: configuration.honorCipherOrder,
|
|
169
|
+
key: configuration.key,
|
|
170
|
+
passphrase: configuration.passphrase,
|
|
171
|
+
pfx: configuration.pfx,
|
|
172
|
+
rejectUnauthorized: (_h = configuration.rejectUnauthorized) !== null && _h !== void 0 ? _h : this.getRejectUnauthorized(),
|
|
173
|
+
secureOptions: configuration.secureOptions,
|
|
174
|
+
secureProtocol: configuration.secureProtocol,
|
|
175
|
+
servername,
|
|
176
|
+
sessionIdContext: configuration.sessionIdContext,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
this.createConnection(connectionConfiguration, (error, socket) => {
|
|
180
|
+
log.trace({
|
|
181
|
+
target: connectionConfiguration,
|
|
182
|
+
}, 'connecting');
|
|
183
|
+
// @see https://github.com/nodejs/node/issues/5757#issuecomment-305969057
|
|
184
|
+
if (socket) {
|
|
185
|
+
socket.setTimeout(this.socketConnectionTimeout, () => {
|
|
186
|
+
socket.destroy();
|
|
187
|
+
});
|
|
188
|
+
socket.once('connect', () => {
|
|
189
|
+
log.trace({
|
|
190
|
+
target: connectionConfiguration,
|
|
191
|
+
}, 'connected');
|
|
192
|
+
socket.setTimeout(0);
|
|
193
|
+
});
|
|
194
|
+
socket.once('secureConnect', () => {
|
|
195
|
+
log.trace({
|
|
196
|
+
target: connectionConfiguration,
|
|
197
|
+
}, 'connected (secure)');
|
|
198
|
+
socket.setTimeout(0);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
if (error) {
|
|
202
|
+
request.emit('error', error);
|
|
203
|
+
}
|
|
204
|
+
else if (socket) {
|
|
205
|
+
log.debug('created socket');
|
|
206
|
+
socket.on('error', (socketError) => {
|
|
207
|
+
log.error({
|
|
208
|
+
error: (0, serialize_error_1.serializeError)(socketError),
|
|
209
|
+
}, 'socket error');
|
|
210
|
+
});
|
|
211
|
+
request.onSocket(socket);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
exports.default = Agent;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AgentType, ConnectionCallbackType, ConnectionConfigurationType, GetUrlProxyMethodType, IsProxyConfiguredMethodType, MustUrlUseProxyMethodType } from '../types';
|
|
2
|
+
import Agent from './Agent';
|
|
3
|
+
declare class HttpProxyAgent extends Agent {
|
|
4
|
+
constructor(isProxyConfigured: IsProxyConfiguredMethodType, mustUrlUseProxy: MustUrlUseProxyMethodType, getUrlProxy: GetUrlProxyMethodType, fallbackAgent: AgentType, socketConnectionTimeout: number, ca: string[] | string | undefined);
|
|
5
|
+
createConnection(configuration: ConnectionConfigurationType, callback: ConnectionCallbackType): void;
|
|
6
|
+
}
|
|
7
|
+
export default HttpProxyAgent;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const net_1 = __importDefault(require("net"));
|
|
7
|
+
const Agent_1 = __importDefault(require("./Agent"));
|
|
8
|
+
class HttpProxyAgent extends Agent_1.default {
|
|
9
|
+
// @see https://github.com/sindresorhus/eslint-plugin-unicorn/issues/169#issuecomment-486980290
|
|
10
|
+
constructor(isProxyConfigured, mustUrlUseProxy, getUrlProxy, fallbackAgent, socketConnectionTimeout, ca) {
|
|
11
|
+
super(isProxyConfigured, mustUrlUseProxy, getUrlProxy, fallbackAgent, socketConnectionTimeout, ca);
|
|
12
|
+
this.protocol = 'http:';
|
|
13
|
+
this.defaultPort = 80;
|
|
14
|
+
}
|
|
15
|
+
createConnection(configuration, callback) {
|
|
16
|
+
const socket = net_1.default.connect(configuration.proxy.port, configuration.proxy.hostname);
|
|
17
|
+
callback(null, socket);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.default = HttpProxyAgent;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AgentType, ConnectionCallbackType, ConnectionConfigurationType, GetUrlProxyMethodType, IsProxyConfiguredMethodType, MustUrlUseProxyMethodType } from '../types';
|
|
2
|
+
import Agent from './Agent';
|
|
3
|
+
declare class HttpsProxyAgent extends Agent {
|
|
4
|
+
constructor(isProxyConfigured: IsProxyConfiguredMethodType, mustUrlUseProxy: MustUrlUseProxyMethodType, getUrlProxy: GetUrlProxyMethodType, fallbackAgent: AgentType, socketConnectionTimeout: number, ca: string[] | string | undefined);
|
|
5
|
+
createConnection(configuration: ConnectionConfigurationType, callback: ConnectionCallbackType): void;
|
|
6
|
+
}
|
|
7
|
+
export default HttpsProxyAgent;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const net_1 = __importDefault(require("net"));
|
|
7
|
+
const tls_1 = __importDefault(require("tls"));
|
|
8
|
+
const Agent_1 = __importDefault(require("./Agent"));
|
|
9
|
+
class HttpsProxyAgent extends Agent_1.default {
|
|
10
|
+
constructor(isProxyConfigured, mustUrlUseProxy, getUrlProxy, fallbackAgent, socketConnectionTimeout, ca) {
|
|
11
|
+
super(isProxyConfigured, mustUrlUseProxy, getUrlProxy, fallbackAgent, socketConnectionTimeout, ca);
|
|
12
|
+
this.protocol = 'https:';
|
|
13
|
+
this.defaultPort = 443;
|
|
14
|
+
}
|
|
15
|
+
createConnection(configuration, callback) {
|
|
16
|
+
const socket = net_1.default.connect(configuration.proxy.port, configuration.proxy.hostname);
|
|
17
|
+
socket.on('error', (error) => {
|
|
18
|
+
callback(error);
|
|
19
|
+
});
|
|
20
|
+
socket.once('data', (data) => {
|
|
21
|
+
var _a;
|
|
22
|
+
// Proxies with HTTPS as protocal are not allowed by parseProxyUrl(), so it should be safe to assume that the response is plain text
|
|
23
|
+
const statusLine = data.toString().split('\r\n')[0];
|
|
24
|
+
const statusLineExp = /^HTTP\/(\d)\.(\d) (\d{3}) ?(.*)$/;
|
|
25
|
+
const statusCode = (_a = statusLineExp.exec(statusLine)) === null || _a === void 0 ? void 0 : _a[3];
|
|
26
|
+
if (typeof statusCode === 'string' && Number(statusCode) >= 400) {
|
|
27
|
+
const error = new Error(`Proxy server refused connecting to '${configuration.host}:${configuration.port}' (${statusLine})`);
|
|
28
|
+
socket.destroy();
|
|
29
|
+
callback(error);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const secureSocket = tls_1.default.connect({
|
|
33
|
+
...configuration.tls,
|
|
34
|
+
socket,
|
|
35
|
+
});
|
|
36
|
+
callback(null, secureSocket);
|
|
37
|
+
});
|
|
38
|
+
let connectMessage = '';
|
|
39
|
+
connectMessage += 'CONNECT ' + configuration.host + ':' + configuration.port + ' HTTP/1.1\r\n';
|
|
40
|
+
connectMessage += 'Host: ' + configuration.host + ':' + configuration.port + '\r\n';
|
|
41
|
+
if (configuration.proxy.authorization) {
|
|
42
|
+
connectMessage += 'Proxy-Authorization: Basic ' + Buffer.from(configuration.proxy.authorization).toString('base64') + '\r\n';
|
|
43
|
+
}
|
|
44
|
+
connectMessage += '\r\n';
|
|
45
|
+
socket.write(connectMessage);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.default = HttpsProxyAgent;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.HttpsProxyAgent = exports.HttpProxyAgent = exports.Agent = void 0;
|
|
7
|
+
var Agent_1 = require("./Agent");
|
|
8
|
+
Object.defineProperty(exports, "Agent", { enumerable: true, get: function () { return __importDefault(Agent_1).default; } });
|
|
9
|
+
var HttpProxyAgent_1 = require("./HttpProxyAgent");
|
|
10
|
+
Object.defineProperty(exports, "HttpProxyAgent", { enumerable: true, get: function () { return __importDefault(HttpProxyAgent_1).default; } });
|
|
11
|
+
var HttpsProxyAgent_1 = require("./HttpsProxyAgent");
|
|
12
|
+
Object.defineProperty(exports, "HttpsProxyAgent", { enumerable: true, get: function () { return __importDefault(HttpsProxyAgent_1).default; } });
|
package/dist/errors.d.ts
ADDED
package/dist/errors.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnexpectedStateError = void 0;
|
|
4
|
+
class UnexpectedStateError extends Error {
|
|
5
|
+
constructor(message, code = 'UNEXPECTED_STATE_ERROR') {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.UnexpectedStateError = UnexpectedStateError;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ProxyAgentConfigurationInputType } from '../types';
|
|
2
|
+
declare const _default: (configurationInput?: ProxyAgentConfigurationInputType) => {
|
|
3
|
+
HTTP_PROXY: string | null;
|
|
4
|
+
HTTPS_PROXY: string | null;
|
|
5
|
+
NO_PROXY: string | null;
|
|
6
|
+
};
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const http_1 = __importDefault(require("http"));
|
|
7
|
+
const https_1 = __importDefault(require("https"));
|
|
8
|
+
const gte_1 = __importDefault(require("semver/functions/gte"));
|
|
9
|
+
const Logger_1 = require("../Logger");
|
|
10
|
+
const classes_1 = require("../classes");
|
|
11
|
+
const errors_1 = require("../errors");
|
|
12
|
+
const utilities_1 = require("../utilities");
|
|
13
|
+
const parseBoolean_1 = require("../utilities/parseBoolean");
|
|
14
|
+
const createProxyController_1 = __importDefault(require("./createProxyController"));
|
|
15
|
+
const httpGet = http_1.default.get;
|
|
16
|
+
const httpRequest = http_1.default.request;
|
|
17
|
+
const httpsGet = https_1.default.get;
|
|
18
|
+
const httpsRequest = https_1.default.request;
|
|
19
|
+
const log = Logger_1.logger.child({
|
|
20
|
+
namespace: 'createGlobalProxyAgent',
|
|
21
|
+
});
|
|
22
|
+
const defaultConfigurationInput = {
|
|
23
|
+
environmentVariableNamespace: undefined,
|
|
24
|
+
forceGlobalAgent: undefined,
|
|
25
|
+
socketConnectionTimeout: 60000,
|
|
26
|
+
};
|
|
27
|
+
const createConfiguration = (configurationInput) => {
|
|
28
|
+
// oxlint-disable-next-line node/no-process-env
|
|
29
|
+
const environment = process.env;
|
|
30
|
+
const defaultConfiguration = {
|
|
31
|
+
environmentVariableNamespace: typeof environment.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE === 'string' ? environment.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE : 'GLOBAL_AGENT_',
|
|
32
|
+
forceGlobalAgent: typeof environment.GLOBAL_AGENT_FORCE_GLOBAL_AGENT === 'string' ? (0, parseBoolean_1.parseBoolean)(environment.GLOBAL_AGENT_FORCE_GLOBAL_AGENT) : true,
|
|
33
|
+
socketConnectionTimeout: typeof environment.GLOBAL_AGENT_SOCKET_CONNECTION_TIMEOUT === 'string' ? Number.parseInt(environment.GLOBAL_AGENT_SOCKET_CONNECTION_TIMEOUT, 10) : defaultConfigurationInput.socketConnectionTimeout,
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
...defaultConfiguration,
|
|
37
|
+
...Object.fromEntries(Object.entries(configurationInput).filter(([, v]) => v !== undefined)),
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
exports.default = (configurationInput = defaultConfigurationInput) => {
|
|
41
|
+
var _a, _b, _c;
|
|
42
|
+
const configuration = createConfiguration(configurationInput);
|
|
43
|
+
if (configurationInput.logger) {
|
|
44
|
+
(0, Logger_1.setLogger)(configurationInput.logger);
|
|
45
|
+
}
|
|
46
|
+
const proxyController = (0, createProxyController_1.default)();
|
|
47
|
+
// oxlint-disable-next-line node/no-process-env
|
|
48
|
+
proxyController.HTTP_PROXY = (_a = process.env[configuration.environmentVariableNamespace + 'HTTP_PROXY']) !== null && _a !== void 0 ? _a : null;
|
|
49
|
+
// oxlint-disable-next-line node/no-process-env
|
|
50
|
+
proxyController.HTTPS_PROXY = (_b = process.env[configuration.environmentVariableNamespace + 'HTTPS_PROXY']) !== null && _b !== void 0 ? _b : null;
|
|
51
|
+
// oxlint-disable-next-line node/no-process-env
|
|
52
|
+
proxyController.NO_PROXY = (_c = process.env[configuration.environmentVariableNamespace + 'NO_PROXY']) !== null && _c !== void 0 ? _c : null;
|
|
53
|
+
log.info({
|
|
54
|
+
configuration,
|
|
55
|
+
state: proxyController,
|
|
56
|
+
}, 'global agent has been initialized');
|
|
57
|
+
const mustUrlUseProxy = (getProxy) => {
|
|
58
|
+
return (url) => {
|
|
59
|
+
if (!getProxy()) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
if (!proxyController.NO_PROXY) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
return !(0, utilities_1.isUrlMatchingNoProxy)(url, proxyController.NO_PROXY);
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
const getUrlProxy = (getProxy) => {
|
|
69
|
+
return () => {
|
|
70
|
+
const proxy = getProxy();
|
|
71
|
+
if (!proxy) {
|
|
72
|
+
throw new errors_1.UnexpectedStateError('HTTP(S) proxy must be configured.');
|
|
73
|
+
}
|
|
74
|
+
return (0, utilities_1.parseProxyUrl)(proxy);
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
const getHttpProxy = () => {
|
|
78
|
+
return proxyController.HTTP_PROXY;
|
|
79
|
+
};
|
|
80
|
+
const BoundHttpProxyAgent = class extends classes_1.HttpProxyAgent {
|
|
81
|
+
constructor() {
|
|
82
|
+
super(() => {
|
|
83
|
+
return Boolean(getHttpProxy());
|
|
84
|
+
}, mustUrlUseProxy(getHttpProxy), getUrlProxy(getHttpProxy), http_1.default.globalAgent, configuration.socketConnectionTimeout, configuration.ca);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const httpAgent = new BoundHttpProxyAgent();
|
|
88
|
+
const getHttpsProxy = () => {
|
|
89
|
+
var _a;
|
|
90
|
+
return (_a = proxyController.HTTPS_PROXY) !== null && _a !== void 0 ? _a : proxyController.HTTP_PROXY;
|
|
91
|
+
};
|
|
92
|
+
const BoundHttpsProxyAgent = class extends classes_1.HttpsProxyAgent {
|
|
93
|
+
constructor() {
|
|
94
|
+
super(() => {
|
|
95
|
+
return Boolean(getHttpsProxy());
|
|
96
|
+
}, mustUrlUseProxy(getHttpsProxy), getUrlProxy(getHttpsProxy), https_1.default.globalAgent, configuration.socketConnectionTimeout, configuration.ca);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const httpsAgent = new BoundHttpsProxyAgent();
|
|
100
|
+
// Overriding globalAgent was added in v11.7.
|
|
101
|
+
// @see https://nodejs.org/uk/blog/release/v11.7.0/
|
|
102
|
+
if ((0, gte_1.default)(process.version, 'v11.7.0')) {
|
|
103
|
+
// @see https://github.com/facebook/flow/issues/7670
|
|
104
|
+
// @ts-expect-error Node.js version compatibility
|
|
105
|
+
http_1.default.globalAgent = httpAgent;
|
|
106
|
+
// @ts-expect-error Node.js version compatibility
|
|
107
|
+
https_1.default.globalAgent = httpsAgent;
|
|
108
|
+
}
|
|
109
|
+
// The reason this logic is used in addition to overriding http(s).globalAgent
|
|
110
|
+
// is because there is no guarantee that we set http(s).globalAgent variable
|
|
111
|
+
// before an instance of http(s).Agent has been already constructed by someone,
|
|
112
|
+
// e.g. Stripe SDK creates instances of http(s).Agent at the top-level.
|
|
113
|
+
// @see https://github.com/gajus/global-agent/pull/13
|
|
114
|
+
//
|
|
115
|
+
// We still want to override http(s).globalAgent when possible to enable logic
|
|
116
|
+
// in `bindHttpMethod`.
|
|
117
|
+
if ((0, gte_1.default)(process.version, 'v10.0.0')) {
|
|
118
|
+
// @ts-expect-error seems like we are using wrong type for httpAgent
|
|
119
|
+
http_1.default.get = (0, utilities_1.bindHttpMethod)(httpGet, httpAgent, configuration.forceGlobalAgent);
|
|
120
|
+
// @ts-expect-error seems like we are using wrong type for httpAgent
|
|
121
|
+
http_1.default.request = (0, utilities_1.bindHttpMethod)(httpRequest, httpAgent, configuration.forceGlobalAgent);
|
|
122
|
+
// @ts-expect-error seems like we are using wrong type for httpAgent
|
|
123
|
+
https_1.default.get = (0, utilities_1.bindHttpMethod)(httpsGet, httpsAgent, configuration.forceGlobalAgent);
|
|
124
|
+
// @ts-expect-error seems like we are using wrong type for httpAgent
|
|
125
|
+
https_1.default.request = (0, utilities_1.bindHttpMethod)(httpsRequest, httpsAgent, configuration.forceGlobalAgent);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
log.warn('attempt to initialize global-agent in unsupported Node.js version was ignored');
|
|
129
|
+
}
|
|
130
|
+
return proxyController;
|
|
131
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|