global-agent 4.0.0 → 4.1.1
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/.github/workflows/feature.yaml +5 -2
- package/.github/workflows/main.yaml +21 -2
- package/.gitignore +0 -2
- package/README.md +34 -16
- package/package.json +7 -29
- package/src/Logger.ts +68 -8
- package/src/classes/Agent.ts +6 -4
- package/{test/global-agent/factories/createGlobalProxyAgent.ts → src/factories/createGlobalProxyAgent.test.ts} +109 -108
- package/src/factories/createGlobalProxyAgent.ts +13 -6
- package/src/factories/createProxyController.test.ts +38 -0
- package/src/factories/createProxyController.ts +5 -3
- package/src/index.ts +3 -0
- package/src/routines/bootstrap.ts +4 -2
- package/src/types.ts +4 -0
- package/src/utilities/isUrlMatchingNoProxy.test.ts +77 -0
- package/src/utilities/isUrlMatchingNoProxy.ts +1 -1
- package/src/utilities/parseProxyUrl.test.ts +35 -0
- package/vitest.config.ts +11 -0
- package/.eslintignore +0 -1
- package/.eslintrc +0 -27
- package/test/.eslintrc +0 -10
- package/test/global-agent/factories/createProxyController.ts +0 -37
- package/test/global-agent/utilities/isUrlMatchingNoProxy.ts +0 -62
- package/test/global-agent/utilities/parseProxyUrl.ts +0 -38
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
jobs:
|
|
2
2
|
test:
|
|
3
|
-
name: Test
|
|
3
|
+
name: Test (Node ${{ matrix.node-version }})
|
|
4
4
|
runs-on: ubuntu-latest
|
|
5
|
+
strategy:
|
|
6
|
+
matrix:
|
|
7
|
+
node-version: ['20', '22', '24']
|
|
5
8
|
steps:
|
|
6
9
|
- name: setup repository
|
|
7
10
|
uses: actions/checkout@v3
|
|
@@ -10,7 +13,7 @@ jobs:
|
|
|
10
13
|
- name: setup node.js
|
|
11
14
|
uses: actions/setup-node@v4
|
|
12
15
|
with:
|
|
13
|
-
node-version:
|
|
16
|
+
node-version: ${{ matrix.node-version }}
|
|
14
17
|
- name: setup npm
|
|
15
18
|
uses: npm/action-setup@v4
|
|
16
19
|
with:
|
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
jobs:
|
|
2
|
+
test:
|
|
3
|
+
name: Test (Node ${{ matrix.node-version }})
|
|
4
|
+
runs-on: ubuntu-latest
|
|
5
|
+
strategy:
|
|
6
|
+
matrix:
|
|
7
|
+
node-version: ['20', '22', '24']
|
|
8
|
+
steps:
|
|
9
|
+
- name: setup repository
|
|
10
|
+
uses: actions/checkout@v3
|
|
11
|
+
with:
|
|
12
|
+
fetch-depth: 0
|
|
13
|
+
- name: setup node.js
|
|
14
|
+
uses: actions/setup-node@v4
|
|
15
|
+
with:
|
|
16
|
+
node-version: ${{ matrix.node-version }}
|
|
17
|
+
- run: npm install
|
|
18
|
+
- run: npm run lint
|
|
19
|
+
- run: npm run test
|
|
20
|
+
- run: npm run build
|
|
21
|
+
timeout-minutes: 10
|
|
2
22
|
release:
|
|
23
|
+
needs: test
|
|
3
24
|
environment: release
|
|
4
25
|
name: Release
|
|
5
26
|
permissions:
|
|
@@ -18,8 +39,6 @@ jobs:
|
|
|
18
39
|
with:
|
|
19
40
|
node-version: '24'
|
|
20
41
|
- run: npm install
|
|
21
|
-
- run: npm run lint
|
|
22
|
-
- run: npm run test
|
|
23
42
|
- run: npm run build
|
|
24
43
|
- env:
|
|
25
44
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
package/.gitignore
CHANGED
package/README.md
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# global-agent
|
|
2
2
|
|
|
3
|
-
[](https://coveralls.io/github/gajus/global-agent)
|
|
4
3
|
[](https://www.npmjs.org/package/global-agent)
|
|
5
4
|
[](https://github.com/gajus/canonical)
|
|
6
5
|
[](https://twitter.com/kuizinas)
|
|
@@ -12,7 +11,6 @@ Global HTTP/HTTPS proxy configurable using environment variables.
|
|
|
12
11
|
* [Setup proxy using `bootstrap` routine](#setup-proxy-using-bootstrap-routine)
|
|
13
12
|
* [Runtime configuration](#runtime-configuration)
|
|
14
13
|
* [Exclude URLs](#exclude-urls)
|
|
15
|
-
* [Enable logging](#enable-logging)
|
|
16
14
|
* [API](#api)
|
|
17
15
|
* [`createGlobalProxyAgent`](#createglobalproxyagent)
|
|
18
16
|
* [Environment variables](#environment-variables)
|
|
@@ -142,20 +140,6 @@ says to contact all machines with the 'foo.com' TLD and 'baz.com' domains direct
|
|
|
142
140
|
|
|
143
141
|
The environment variable `GLOBAL_AGENT_HTTPS_PROXY` can be set to specify a separate proxy for HTTPS requests. When this variable is not set `GLOBAL_AGENT_HTTP_PROXY` is used for both HTTP and HTTPS requests.
|
|
144
142
|
|
|
145
|
-
### Enable logging
|
|
146
|
-
|
|
147
|
-
`global-agent` is using [`roarr`](https://www.npmjs.com/package/roarr) logger to log HTTP requests and response (HTTP status code and headers), e.g.
|
|
148
|
-
|
|
149
|
-
```json
|
|
150
|
-
{"context":{"program":"global-agent","namespace":"Agent","logLevel":10,"destination":"http://gajus.com","proxy":"http://127.0.0.1:8076"},"message":"proxying request","sequence":1,"time":1556269669663,"version":"1.0.0"}
|
|
151
|
-
{"context":{"program":"global-agent","namespace":"Agent","logLevel":10,"headers":{"content-type":"text/plain","content-length":"2","date":"Fri, 26 Apr 2019 12:07:50 GMT","connection":"close"},"requestId":6,"statusCode":200},"message":"proxying response","sequence":2,"time":1557133856955,"version":"1.0.0"}
|
|
152
|
-
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
Export `ROARR_LOG=true` environment variable to enable log printing to stdout.
|
|
156
|
-
|
|
157
|
-
Use [`roarr-cli`](https://github.com/gajus/roarr-cli) program to pretty-print the logs.
|
|
158
|
-
|
|
159
143
|
## API
|
|
160
144
|
|
|
161
145
|
### `createGlobalProxyAgent`
|
|
@@ -166,18 +150,52 @@ Use [`roarr-cli`](https://github.com/gajus/roarr-cli) program to pretty-print th
|
|
|
166
150
|
* @property forceGlobalAgent Forces to use `global-agent` HTTP(S) agent even when request was explicitly constructed with another agent. (Default: `true`)
|
|
167
151
|
* @property socketConnectionTimeout Destroys socket if connection is not established within the timeout. (Default: `60000`)
|
|
168
152
|
* @property ca Single CA certificate or an array of CA certificates that is trusted for secure connections to the registry.
|
|
153
|
+
* @property logger Custom logger instance for debug logging. Must implement `child`, `debug`, `error`, `info`, `trace`, and `warn` methods.
|
|
169
154
|
*/
|
|
170
155
|
type ProxyAgentConfigurationInputType = {|
|
|
171
156
|
+environmentVariableNamespace?: string,
|
|
172
157
|
+forceGlobalAgent?: boolean,
|
|
173
158
|
+socketConnectionTimeout?: number,
|
|
174
159
|
+ca?: string[] | string,
|
|
160
|
+
+logger?: Logger,
|
|
175
161
|
|};
|
|
176
162
|
|
|
177
163
|
(configurationInput: ProxyAgentConfigurationInputType) => ProxyAgentConfigurationType;
|
|
178
164
|
|
|
179
165
|
```
|
|
180
166
|
|
|
167
|
+
### Custom Logger
|
|
168
|
+
|
|
169
|
+
You can provide a custom logger to `global-agent` for debugging purposes. The logger must implement the following interface:
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
type Logger = {
|
|
173
|
+
child: (context: object) => Logger,
|
|
174
|
+
debug: (context: object | string, message?: string) => void,
|
|
175
|
+
error: (context: object | string, message?: string) => void,
|
|
176
|
+
info: (context: object | string, message?: string) => void,
|
|
177
|
+
trace: (context: object | string, message?: string) => void,
|
|
178
|
+
warn: (context: object | string, message?: string) => void,
|
|
179
|
+
};
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Example using a custom logger:
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
import { createGlobalProxyAgent } from 'global-agent';
|
|
186
|
+
|
|
187
|
+
createGlobalProxyAgent({
|
|
188
|
+
logger: {
|
|
189
|
+
child: () => logger,
|
|
190
|
+
debug: console.debug,
|
|
191
|
+
error: console.error,
|
|
192
|
+
info: console.info,
|
|
193
|
+
trace: console.trace,
|
|
194
|
+
warn: console.warn,
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
181
199
|
### Environment variables
|
|
182
200
|
|
|
183
201
|
|Name|Description|Default|
|
package/package.json
CHANGED
|
@@ -2,38 +2,24 @@
|
|
|
2
2
|
"author": {
|
|
3
3
|
"email": "gajus@gajus.com",
|
|
4
4
|
"name": "Gajus Kuizinas",
|
|
5
|
-
"url": "
|
|
6
|
-
},
|
|
7
|
-
"ava": {
|
|
8
|
-
"extensions": [
|
|
9
|
-
"ts"
|
|
10
|
-
],
|
|
11
|
-
"files": [
|
|
12
|
-
"test/global-agent/**/*"
|
|
13
|
-
],
|
|
14
|
-
"require": [
|
|
15
|
-
"ts-node/register/transpile-only"
|
|
16
|
-
]
|
|
5
|
+
"url": "https://gajus.com"
|
|
17
6
|
},
|
|
18
7
|
"dependencies": {
|
|
19
8
|
"es6-error": "^4.1.1",
|
|
20
9
|
"globalthis": "^1.0.2",
|
|
21
10
|
"matcher": "^4.0.0",
|
|
22
11
|
"omit-undefined": "^1.0.1",
|
|
23
|
-
"roarr": "^7.0.3",
|
|
24
12
|
"semver": "^7.3.5",
|
|
25
13
|
"serialize-error": "^8.1.0"
|
|
26
14
|
},
|
|
27
15
|
"description": "Global HTTP/HTTPS proxy configurable using environment variables.",
|
|
28
16
|
"devDependencies": {
|
|
29
|
-
"@ava/babel": "^2.0.0",
|
|
30
17
|
"@babel/cli": "^7.14.8",
|
|
31
18
|
"@babel/core": "^7.14.8",
|
|
32
19
|
"@babel/node": "^7.14.7",
|
|
33
20
|
"@babel/plugin-transform-flow-strip-types": "^7.14.5",
|
|
34
21
|
"@babel/preset-env": "^7.14.8",
|
|
35
22
|
"@babel/register": "^7.14.5",
|
|
36
|
-
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
|
37
23
|
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
38
24
|
"@semantic-release/github": "^12.0.3",
|
|
39
25
|
"@semantic-release/npm": "^13.1.3",
|
|
@@ -42,24 +28,20 @@
|
|
|
42
28
|
"@types/request": "^2.48.6",
|
|
43
29
|
"@types/semver": "^7.3.8",
|
|
44
30
|
"@types/sinon": "^10.0.2",
|
|
45
|
-
"ava": "^3.15.0",
|
|
46
31
|
"axios": "^0.21.1",
|
|
47
|
-
"babel-plugin-istanbul": "^6.0.0",
|
|
48
32
|
"babel-plugin-transform-export-default-name": "^2.1.0",
|
|
49
|
-
"coveralls": "^3.1.1",
|
|
50
33
|
"del-cli": "^4.0.1",
|
|
51
|
-
"eslint": "^7.31.0",
|
|
52
|
-
"eslint-config-canonical": "^26.2.3",
|
|
53
34
|
"get-port": "^5.1.1",
|
|
54
35
|
"got": "^11.8.2",
|
|
55
36
|
"husky": "^7.0.1",
|
|
56
|
-
"
|
|
37
|
+
"oxlint": "^1.43.0",
|
|
57
38
|
"pem": "^1.14.4",
|
|
58
39
|
"request": "^2.88.2",
|
|
59
40
|
"semantic-release": "^25.0.3",
|
|
60
41
|
"sinon": "^11.1.2",
|
|
61
42
|
"ts-node": "^10.1.0",
|
|
62
|
-
"typescript": "^4.3.5"
|
|
43
|
+
"typescript": "^4.3.5",
|
|
44
|
+
"vitest": "^4.0.18"
|
|
63
45
|
},
|
|
64
46
|
"engines": {
|
|
65
47
|
"node": ">=10.0"
|
|
@@ -78,20 +60,16 @@
|
|
|
78
60
|
"license": "BSD-3-Clause",
|
|
79
61
|
"main": "./dist/src/index.js",
|
|
80
62
|
"name": "global-agent",
|
|
81
|
-
"nyc": {
|
|
82
|
-
"extends": "@istanbuljs/nyc-config-typescript",
|
|
83
|
-
"all": true
|
|
84
|
-
},
|
|
85
63
|
"repository": {
|
|
86
64
|
"type": "git",
|
|
87
65
|
"url": "https://github.com/gajus/global-agent"
|
|
88
66
|
},
|
|
89
67
|
"scripts": {
|
|
90
68
|
"build": "del-cli ./dist && tsc",
|
|
91
|
-
"lint": "
|
|
92
|
-
"test": "
|
|
69
|
+
"lint": "oxlint ./src && tsc",
|
|
70
|
+
"test": "vitest run",
|
|
93
71
|
"create-readme": "gitdown ./.README/README.md --output-file ./README.md"
|
|
94
72
|
},
|
|
95
73
|
"typings": "./dist/src/index.d.ts",
|
|
96
|
-
"version": "4.
|
|
74
|
+
"version": "4.1.1"
|
|
97
75
|
}
|
package/src/Logger.ts
CHANGED
|
@@ -1,10 +1,70 @@
|
|
|
1
|
-
|
|
2
|
-
Roarr,
|
|
3
|
-
} from 'roarr';
|
|
1
|
+
export type LogMethod = (context: object | string, message?: string) => void;
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
export type Logger = {
|
|
4
|
+
child: (context: object) => Logger,
|
|
5
|
+
debug: LogMethod,
|
|
6
|
+
error: LogMethod,
|
|
7
|
+
info: LogMethod,
|
|
8
|
+
trace: LogMethod,
|
|
9
|
+
warn: LogMethod,
|
|
10
|
+
};
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
// oxlint-disable-next-line @typescript-eslint/no-empty-function
|
|
13
|
+
const noop = () => {};
|
|
14
|
+
|
|
15
|
+
const createNoopLogger = (): Logger => {
|
|
16
|
+
return {
|
|
17
|
+
child: () => {
|
|
18
|
+
return createNoopLogger();
|
|
19
|
+
},
|
|
20
|
+
debug: noop,
|
|
21
|
+
error: noop,
|
|
22
|
+
info: noop,
|
|
23
|
+
trace: noop,
|
|
24
|
+
warn: noop,
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
let currentLogger: Logger = createNoopLogger();
|
|
29
|
+
|
|
30
|
+
export const setLogger = (newLogger: Logger): void => {
|
|
31
|
+
currentLogger = newLogger;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const createDelegatingLogger = (getContext: () => object): Logger => {
|
|
35
|
+
const getLogger = () => {
|
|
36
|
+
let targetLogger = currentLogger;
|
|
37
|
+
for (const [key, value] of Object.entries(getContext())) {
|
|
38
|
+
targetLogger = targetLogger.child({[key]: value});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return targetLogger;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
child: (context: object) => {
|
|
46
|
+
return createDelegatingLogger(() => {
|
|
47
|
+
return {...getContext(), ...context};
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
debug: (context, message) => {
|
|
51
|
+
getLogger().debug(context, message);
|
|
52
|
+
},
|
|
53
|
+
error: (context, message) => {
|
|
54
|
+
getLogger().error(context, message);
|
|
55
|
+
},
|
|
56
|
+
info: (context, message) => {
|
|
57
|
+
getLogger().info(context, message);
|
|
58
|
+
},
|
|
59
|
+
trace: (context, message) => {
|
|
60
|
+
getLogger().trace(context, message);
|
|
61
|
+
},
|
|
62
|
+
warn: (context, message) => {
|
|
63
|
+
getLogger().warn(context, message);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const logger = createDelegatingLogger(() => {
|
|
69
|
+
return {package: 'global-agent'};
|
|
70
|
+
});
|
package/src/classes/Agent.ts
CHANGED
|
@@ -4,7 +4,9 @@ import net from 'net';
|
|
|
4
4
|
import {
|
|
5
5
|
serializeError,
|
|
6
6
|
} from 'serialize-error';
|
|
7
|
-
import
|
|
7
|
+
import {
|
|
8
|
+
logger,
|
|
9
|
+
} from '../Logger';
|
|
8
10
|
import type {
|
|
9
11
|
AgentType,
|
|
10
12
|
ConnectionCallbackType,
|
|
@@ -15,7 +17,7 @@ import type {
|
|
|
15
17
|
ProtocolType,
|
|
16
18
|
} from '../types';
|
|
17
19
|
|
|
18
|
-
const log =
|
|
20
|
+
const log = logger.child({
|
|
19
21
|
namespace: 'Agent',
|
|
20
22
|
});
|
|
21
23
|
|
|
@@ -106,7 +108,7 @@ abstract class Agent {
|
|
|
106
108
|
* Evaluate value for tls reject unauthorized variable
|
|
107
109
|
*/
|
|
108
110
|
public getRejectUnauthorized () {
|
|
109
|
-
//
|
|
111
|
+
// oxlint-disable-next-line node/no-process-env
|
|
110
112
|
const rejectUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED;
|
|
111
113
|
let returnValue = true;
|
|
112
114
|
if (typeof rejectUnauthorized === 'boolean') {
|
|
@@ -134,7 +136,7 @@ abstract class Agent {
|
|
|
134
136
|
} else if (request.method === 'CONNECT') {
|
|
135
137
|
requestUrl = 'https://' + request.path;
|
|
136
138
|
} else {
|
|
137
|
-
requestUrl = this.protocol + '//' + (configuration.hostname ?? configuration.host) + (configuration.port === 80
|
|
139
|
+
requestUrl = this.protocol + '//' + (configuration.hostname ?? configuration.host) + (configuration.port === 80 || configuration.port === 443 ? '' : ':' + configuration.port) + request.path;
|
|
138
140
|
}
|
|
139
141
|
|
|
140
142
|
// If a request should go to a local socket, proxying it through an HTTP
|