undici 4.8.1 → 4.9.2

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.
@@ -0,0 +1,100 @@
1
+ # Class: ProxyAgent
2
+
3
+ Extends: `undici.Dispatcher`
4
+
5
+ A Proxy Agent class that implements the Agent API. It allows the connection through proxy in a simple way.
6
+
7
+ ## `new ProxyAgent([options])`
8
+
9
+ Arguments:
10
+
11
+ * **options** `ProxyAgentOptions` (required) - It extends the `Agent` options.
12
+
13
+ Returns: `ProxyAgent`
14
+
15
+ ### Parameter: `ProxyAgentOptions`
16
+
17
+ Extends: [`AgentOptions`](docs/api/Agent.md#parameter-agentoptions)
18
+
19
+ * **uri** `string` (required) - It can be passed either by a string or a object containing `uri` as string.
20
+
21
+ Examples:
22
+
23
+ ```js
24
+ import { ProxyAgent } from 'undici'
25
+
26
+ const proxyAgent = new ProxyAgent('my.proxy.server')
27
+ // or
28
+ const proxyAgent = new ProxyAgent({ uri: 'my.proxy.server' })
29
+ ```
30
+
31
+ #### Example - Basic ProxyAgent instantiation
32
+
33
+ This will instantiate the ProxyAgent. It will not do anything until registered as the agent to use with requests.
34
+
35
+ ```js
36
+ import { ProxyAgent } from 'undici'
37
+
38
+ const proxyAgent = new ProxyAgent('my.proxy.server')
39
+ ```
40
+
41
+ #### Example - Basic Proxy Request with global agent dispatcher
42
+
43
+ ```js
44
+ import { setGlobalDispatcher, request, ProxyAgent } from 'undici'
45
+
46
+ const proxyAgent = new ProxyAgent('my.proxy.server')
47
+ setGlobalDispatcher(proxyAgent)
48
+
49
+ const { statusCode, body } = await request('http://localhost:3000/foo')
50
+
51
+ console.log('response received', statusCode) // response received 200
52
+
53
+ for await (const data of body) {
54
+ console.log('data', data.toString('utf8')) // data foo
55
+ }
56
+ ```
57
+
58
+ #### Example - Basic Proxy Request with local agent dispatcher
59
+
60
+ ```js
61
+ import { ProxyAgent, request } from 'undici'
62
+
63
+ const proxyAgent = new ProxyAgent('my.proxy.server')
64
+
65
+ const {
66
+ statusCode,
67
+ body
68
+ } = await request('http://localhost:3000/foo', { dispatcher: proxyAgent })
69
+
70
+ console.log('response received', statusCode) // response received 200
71
+
72
+ for await (const data of body) {
73
+ console.log('data', data.toString('utf8')) // data foo
74
+ }
75
+ ```
76
+
77
+ ### `ProxyAgent.close()`
78
+
79
+ Closes the proxy agent and waits for registered pools and clients to also close before resolving.
80
+
81
+ Returns: `Promise<void>`
82
+
83
+ #### Example - clean up after tests are complete
84
+
85
+ ```js
86
+ import { ProxyAgent, setGlobalDispatcher } from 'undici'
87
+
88
+ const proxyAgent = new ProxyAgent('my.proxy.server')
89
+ setGlobalDispatcher(proxyAgent)
90
+
91
+ await proxyAgent.close()
92
+ ```
93
+
94
+ ### `ProxyAgent.dispatch(options, handlers)`
95
+
96
+ Implements [`Agent.dispatch(options, handlers)`](docs/api/Agent.md#parameter-agentdispatchoptions).
97
+
98
+ ### `ProxyAgent.request(options[, callback])`
99
+
100
+ See [`Dispatcher.request(options [, callback])`](docs/api/Dispatcher.md#clientrequestoptions--callback).
@@ -1,6 +1,9 @@
1
1
  # Connecting through a proxy
2
2
 
3
- Connecting through a proxy is possible by properly configuring the `Client` or `Pool` constructor and request.
3
+ Connecting through a proxy is possible by:
4
+
5
+ - Using [AgentProxy](docs/api/ProxyAgent.md).
6
+ - Configuring `Client` or `Pool` constructor.
4
7
 
5
8
  The proxy url should be passed to the `Client` or `Pool` constructor, while the upstream server url
6
9
  should be added to every request call in the `path`.
package/index.d.ts CHANGED
@@ -10,13 +10,14 @@ import MockClient = require('./types/mock-client')
10
10
  import MockPool = require('./types/mock-pool')
11
11
  import MockAgent = require('./types/mock-agent')
12
12
  import mockErrors = require('./types/mock-errors')
13
+ import ProxyAgent from './types/proxy-agent'
13
14
  import { request, pipeline, stream, connect, upgrade } from './types/api'
14
15
 
15
16
  export * from './types/fetch'
16
17
  export * from './types/file'
17
18
  export * from './types/formdata'
18
19
 
19
- export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, MockClient, MockPool, MockAgent, mockErrors }
20
+ export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, MockClient, MockPool, MockAgent, mockErrors, ProxyAgent }
20
21
  export default Undici
21
22
 
22
23
  declare function Undici(url: string, opts: Pool.Options): Pool
package/index.js CHANGED
@@ -14,6 +14,7 @@ const MockClient = require('./lib/mock/mock-client')
14
14
  const MockAgent = require('./lib/mock/mock-agent')
15
15
  const MockPool = require('./lib/mock/mock-pool')
16
16
  const mockErrors = require('./lib/mock/mock-errors')
17
+ const ProxyAgent = require('./lib/proxy-agent')
17
18
 
18
19
  const nodeVersion = process.versions.node.split('.')
19
20
  const nodeMajor = Number(nodeVersion[0])
@@ -26,6 +27,7 @@ module.exports.Client = Client
26
27
  module.exports.Pool = Pool
27
28
  module.exports.BalancedPool = BalancedPool
28
29
  module.exports.Agent = Agent
30
+ module.exports.ProxyAgent = ProxyAgent
29
31
 
30
32
  module.exports.buildConnector = buildConnector
31
33
  module.exports.errors = errors
package/lib/client.js CHANGED
@@ -62,7 +62,9 @@ const {
62
62
  kBodyTimeout,
63
63
  kStrictContentLength,
64
64
  kConnector,
65
- kMaxRedirections
65
+ kMaxRedirections,
66
+ kMaxRequests,
67
+ kCounter
66
68
  } = require('./core/symbols')
67
69
 
68
70
  const channels = {}
@@ -100,7 +102,8 @@ class Client extends Dispatcher {
100
102
  strictContentLength,
101
103
  maxCachedSessions,
102
104
  maxRedirections,
103
- connect
105
+ connect,
106
+ maxRequestsPerClient
104
107
  } = {}) {
105
108
  super()
106
109
 
@@ -164,6 +167,10 @@ class Client extends Dispatcher {
164
167
  throw new InvalidArgumentError('maxRedirections must be a positive number')
165
168
  }
166
169
 
170
+ if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) {
171
+ throw new InvalidArgumentError('maxRequestsPerClient must be a positive number')
172
+ }
173
+
167
174
  if (typeof connect !== 'function') {
168
175
  connect = buildConnector({
169
176
  ...tls,
@@ -194,6 +201,7 @@ class Client extends Dispatcher {
194
201
  this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 30e3
195
202
  this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength
196
203
  this[kMaxRedirections] = maxRedirections
204
+ this[kMaxRequests] = maxRequestsPerClient
197
205
 
198
206
  // kQueue is built up of 3 sections separated by
199
207
  // the kRunningIdx and kPendingIdx indices.
@@ -397,79 +405,82 @@ class Client extends Dispatcher {
397
405
  }
398
406
  }
399
407
 
400
- const { resolve } = require('path')
401
- const { readFileSync } = require('fs')
402
408
  const constants = require('./llhttp/constants')
403
409
  const EMPTY_BUF = Buffer.alloc(0)
404
410
 
405
- let llhttpInstance
406
- function lazyllhttp () {
407
- if (!llhttpInstance) {
408
- let mod
409
- try {
410
- mod = new WebAssembly.Module(readFileSync(resolve(__dirname, './llhttp/llhttp_simd.wasm')))
411
- } catch (e) {
412
- /* istanbul ignore next */
411
+ async function lazyllhttp () {
412
+ const { resolve } = require('path')
413
+ const { readFile } = require('fs').promises
413
414
 
414
- // We could check if the error was caused by the simd option not
415
- // being enabled, but the occurring of this other error
416
- // * https://github.com/emscripten-core/emscripten/issues/11495
417
- // got me to remove that check to avoid breaking Node 12.
418
- mod = new WebAssembly.Module(readFileSync(resolve(__dirname, './llhttp/llhttp.wasm')))
419
- }
415
+ let mod
416
+ try {
417
+ mod = await WebAssembly.compile(await readFile(resolve(__dirname, './llhttp/llhttp_simd.wasm')))
418
+ } catch (e) {
419
+ /* istanbul ignore next */
420
420
 
421
- llhttpInstance = new WebAssembly.Instance(mod, {
422
- env: {
423
- /* eslint-disable camelcase */
421
+ // We could check if the error was caused by the simd option not
422
+ // being enabled, but the occurring of this other error
423
+ // * https://github.com/emscripten-core/emscripten/issues/11495
424
+ // got me to remove that check to avoid breaking Node 12.
425
+ mod = await WebAssembly.compile(await readFile(resolve(__dirname, './llhttp/llhttp.wasm')))
426
+ }
424
427
 
425
- wasm_on_url: (p, at, len) => {
426
- /* istanbul ignore next */
427
- return 0
428
- },
429
- wasm_on_status: (p, at, len) => {
430
- assert.strictEqual(currentParser.ptr, p)
431
- const start = at - currentBufferPtr
432
- const end = start + len
433
- return currentParser.onStatus(currentBufferRef.slice(start, end)) || 0
434
- },
435
- wasm_on_message_begin: (p) => {
436
- assert.strictEqual(currentParser.ptr, p)
437
- return currentParser.onMessageBegin() || 0
438
- },
439
- wasm_on_header_field: (p, at, len) => {
440
- assert.strictEqual(currentParser.ptr, p)
441
- const start = at - currentBufferPtr
442
- const end = start + len
443
- return currentParser.onHeaderField(currentBufferRef.slice(start, end)) || 0
444
- },
445
- wasm_on_header_value: (p, at, len) => {
446
- assert.strictEqual(currentParser.ptr, p)
447
- const start = at - currentBufferPtr
448
- const end = start + len
449
- return currentParser.onHeaderValue(currentBufferRef.slice(start, end)) || 0
450
- },
451
- wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => {
452
- assert.strictEqual(currentParser.ptr, p)
453
- return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0
454
- },
455
- wasm_on_body: (p, at, len) => {
456
- assert.strictEqual(currentParser.ptr, p)
457
- const start = at - currentBufferPtr
458
- const end = start + len
459
- return currentParser.onBody(currentBufferRef.slice(start, end)) || 0
460
- },
461
- wasm_on_message_complete: (p) => {
462
- assert.strictEqual(currentParser.ptr, p)
463
- return currentParser.onMessageComplete() || 0
464
- }
428
+ return await WebAssembly.instantiate(mod, {
429
+ env: {
430
+ /* eslint-disable camelcase */
465
431
 
466
- /* eslint-enable camelcase */
432
+ wasm_on_url: (p, at, len) => {
433
+ /* istanbul ignore next */
434
+ return 0
435
+ },
436
+ wasm_on_status: (p, at, len) => {
437
+ assert.strictEqual(currentParser.ptr, p)
438
+ const start = at - currentBufferPtr
439
+ const end = start + len
440
+ return currentParser.onStatus(currentBufferRef.slice(start, end)) || 0
441
+ },
442
+ wasm_on_message_begin: (p) => {
443
+ assert.strictEqual(currentParser.ptr, p)
444
+ return currentParser.onMessageBegin() || 0
445
+ },
446
+ wasm_on_header_field: (p, at, len) => {
447
+ assert.strictEqual(currentParser.ptr, p)
448
+ const start = at - currentBufferPtr
449
+ const end = start + len
450
+ return currentParser.onHeaderField(currentBufferRef.slice(start, end)) || 0
451
+ },
452
+ wasm_on_header_value: (p, at, len) => {
453
+ assert.strictEqual(currentParser.ptr, p)
454
+ const start = at - currentBufferPtr
455
+ const end = start + len
456
+ return currentParser.onHeaderValue(currentBufferRef.slice(start, end)) || 0
457
+ },
458
+ wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => {
459
+ assert.strictEqual(currentParser.ptr, p)
460
+ return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0
461
+ },
462
+ wasm_on_body: (p, at, len) => {
463
+ assert.strictEqual(currentParser.ptr, p)
464
+ const start = at - currentBufferPtr
465
+ const end = start + len
466
+ return currentParser.onBody(currentBufferRef.slice(start, end)) || 0
467
+ },
468
+ wasm_on_message_complete: (p) => {
469
+ assert.strictEqual(currentParser.ptr, p)
470
+ return currentParser.onMessageComplete() || 0
467
471
  }
468
- })
469
- }
470
- return llhttpInstance
472
+
473
+ /* eslint-enable camelcase */
474
+ }
475
+ })
471
476
  }
472
477
 
478
+ let llhttpInstance = null
479
+ let llhttpPromise = lazyllhttp()
480
+ .catch(() => {
481
+ // TODO: Emit warning?
482
+ })
483
+
473
484
  let currentParser = null
474
485
  let currentBufferRef = null
475
486
  let currentBufferSize = 0
@@ -480,10 +491,10 @@ const TIMEOUT_BODY = 2
480
491
  const TIMEOUT_IDLE = 3
481
492
 
482
493
  class Parser {
483
- constructor (client, socket) {
494
+ constructor (client, socket, { exports }) {
484
495
  assert(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0)
485
496
 
486
- this.llhttp = lazyllhttp().exports
497
+ this.llhttp = exports
487
498
  this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE)
488
499
  this.client = client
489
500
  this.socket = socket
@@ -1096,7 +1107,7 @@ function onSocketClose () {
1096
1107
  resume(client)
1097
1108
  }
1098
1109
 
1099
- function connect (client) {
1110
+ async function connect (client) {
1100
1111
  assert(!client[kConnecting])
1101
1112
  assert(!client[kSocket])
1102
1113
 
@@ -1128,78 +1139,94 @@ function connect (client) {
1128
1139
  })
1129
1140
  }
1130
1141
 
1131
- client[kConnector]({
1132
- host,
1133
- hostname,
1134
- protocol,
1135
- port,
1136
- servername: client[kServerName]
1137
- }, function (err, socket) {
1142
+ try {
1143
+ const socket = await new Promise((resolve, reject) => {
1144
+ client[kConnector]({
1145
+ host,
1146
+ hostname,
1147
+ protocol,
1148
+ port,
1149
+ servername: client[kServerName]
1150
+ }, (err, socket) => {
1151
+ if (err) {
1152
+ reject(err)
1153
+ } else {
1154
+ resolve(socket)
1155
+ }
1156
+ })
1157
+ })
1158
+
1159
+ if (!llhttpInstance) {
1160
+ llhttpInstance = await llhttpPromise
1161
+ llhttpPromise = null
1162
+ }
1163
+
1138
1164
  client[kConnecting] = false
1139
1165
 
1140
- if (err) {
1141
- if (channels.connectError.hasSubscribers) {
1142
- channels.connectError.publish({
1143
- connectParams: {
1144
- host,
1145
- hostname,
1146
- protocol,
1147
- port,
1148
- servername: client[kServerName]
1149
- },
1150
- connector: client[kConnector],
1151
- error: err
1152
- })
1153
- }
1166
+ assert(socket)
1154
1167
 
1155
- if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') {
1156
- assert(client[kRunning] === 0)
1157
- while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) {
1158
- const request = client[kQueue][client[kPendingIdx]++]
1159
- errorRequest(client, request, err)
1160
- }
1161
- } else {
1162
- onError(client, err)
1163
- }
1168
+ client[kSocket] = socket
1164
1169
 
1165
- client.emit('connectionError', client[kUrl], [client], err)
1166
- } else {
1167
- assert(socket)
1170
+ socket[kNoRef] = false
1171
+ socket[kWriting] = false
1172
+ socket[kReset] = false
1173
+ socket[kBlocking] = false
1174
+ socket[kError] = null
1175
+ socket[kParser] = new Parser(client, socket, llhttpInstance)
1176
+ socket[kClient] = client
1177
+ socket[kCounter] = 0
1178
+ socket[kMaxRequests] = client[kMaxRequests]
1179
+ socket
1180
+ .on('error', onSocketError)
1181
+ .on('readable', onSocketReadable)
1182
+ .on('end', onSocketEnd)
1183
+ .on('close', onSocketClose)
1184
+
1185
+ if (channels.connected.hasSubscribers) {
1186
+ channels.connected.publish({
1187
+ connectParams: {
1188
+ host,
1189
+ hostname,
1190
+ protocol,
1191
+ port,
1192
+ servername: client[kServerName]
1193
+ },
1194
+ connector: client[kConnector],
1195
+ socket
1196
+ })
1197
+ }
1198
+ client.emit('connect', client[kUrl], [client])
1199
+ } catch (err) {
1200
+ client[kConnecting] = false
1168
1201
 
1169
- client[kSocket] = socket
1202
+ if (channels.connectError.hasSubscribers) {
1203
+ channels.connectError.publish({
1204
+ connectParams: {
1205
+ host,
1206
+ hostname,
1207
+ protocol,
1208
+ port,
1209
+ servername: client[kServerName]
1210
+ },
1211
+ connector: client[kConnector],
1212
+ error: err
1213
+ })
1214
+ }
1170
1215
 
1171
- socket[kNoRef] = false
1172
- socket[kWriting] = false
1173
- socket[kReset] = false
1174
- socket[kBlocking] = false
1175
- socket[kError] = null
1176
- socket[kParser] = new Parser(client, socket)
1177
- socket[kClient] = client
1178
- socket
1179
- .on('error', onSocketError)
1180
- .on('readable', onSocketReadable)
1181
- .on('end', onSocketEnd)
1182
- .on('close', onSocketClose)
1183
-
1184
- if (channels.connected.hasSubscribers) {
1185
- channels.connected.publish({
1186
- connectParams: {
1187
- host,
1188
- hostname,
1189
- protocol,
1190
- port,
1191
- servername: client[kServerName]
1192
- },
1193
- connector: client[kConnector],
1194
- socket
1195
- })
1216
+ if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') {
1217
+ assert(client[kRunning] === 0)
1218
+ while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) {
1219
+ const request = client[kQueue][client[kPendingIdx]++]
1220
+ errorRequest(client, request, err)
1196
1221
  }
1197
-
1198
- client.emit('connect', client[kUrl], [client])
1222
+ } else {
1223
+ onError(client, err)
1199
1224
  }
1200
1225
 
1201
- resume(client)
1202
- })
1226
+ client.emit('connectionError', client[kUrl], [client], err)
1227
+ }
1228
+
1229
+ resume(client)
1203
1230
  }
1204
1231
 
1205
1232
  function emitDrain (client) {
@@ -1213,6 +1240,7 @@ function resume (client, sync) {
1213
1240
  }
1214
1241
 
1215
1242
  client[kResuming] = 2
1243
+
1216
1244
  _resume(client, sync)
1217
1245
  client[kResuming] = 0
1218
1246
 
@@ -1445,6 +1473,10 @@ function write (client, request) {
1445
1473
  socket[kReset] = true
1446
1474
  }
1447
1475
 
1476
+ if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) {
1477
+ socket[kReset] = true
1478
+ }
1479
+
1448
1480
  if (blocking) {
1449
1481
  socket[kBlocking] = true
1450
1482
  }
@@ -40,5 +40,8 @@ module.exports = {
40
40
  kHostHeader: Symbol('host header'),
41
41
  kConnector: Symbol('connector'),
42
42
  kStrictContentLength: Symbol('strict content length'),
43
- kMaxRedirections: Symbol('maxRedirections')
43
+ kMaxRedirections: Symbol('maxRedirections'),
44
+ kMaxRequests: Symbol('maxRequestsPerClient'),
45
+ kProxy: Symbol('proxy agent options'),
46
+ kCounter: Symbol('socket request counter')
44
47
  }
@@ -171,7 +171,7 @@ async function fetch (...args) {
171
171
 
172
172
  // 3. If response is a network error, then reject p with a TypeError
173
173
  // and terminate these substeps.
174
- if (response.status === 0) {
174
+ if (response.type === 'error') {
175
175
  p.reject(
176
176
  Object.assign(new TypeError('fetch failed'), { cause: response.error })
177
177
  )
@@ -0,0 +1,59 @@
1
+ 'use strict'
2
+
3
+ const { kClients, kProxy } = require('./core/symbols')
4
+ const url = require('url')
5
+ const Agent = require('./agent')
6
+ const Dispatcher = require('./dispatcher')
7
+ const { InvalidArgumentError } = require('./core/errors')
8
+
9
+ const kAgent = Symbol('proxy agent')
10
+
11
+ class ProxyAgent extends Dispatcher {
12
+ constructor (opts) {
13
+ super(opts)
14
+ this[kProxy] = buildProxyOptions(opts)
15
+
16
+ const agent = new Agent(opts)
17
+ this[kAgent] = agent
18
+
19
+ this[kClients] = agent[kClients]
20
+ }
21
+
22
+ dispatch (opts, handler) {
23
+ const { host } = url.parse(opts.origin)
24
+ return this[kAgent].dispatch(
25
+ {
26
+ ...opts,
27
+ origin: this[kProxy].uri,
28
+ path: opts.origin + opts.path,
29
+ headers: {
30
+ ...opts.headers,
31
+ host
32
+ },
33
+ },
34
+ handler
35
+ )
36
+ }
37
+
38
+ async close () {
39
+ await this[kAgent].close()
40
+ this[kClients].clear()
41
+ }
42
+ }
43
+
44
+ function buildProxyOptions(opts) {
45
+ if (typeof opts === 'string') {
46
+ opts = { uri: opts }
47
+ }
48
+
49
+ if (!opts || !opts.uri) {
50
+ throw new InvalidArgumentError('Proxy opts.uri is mandatory')
51
+ }
52
+
53
+ return {
54
+ uri: opts.uri,
55
+ protocol: opts.protocol || 'https'
56
+ }
57
+ }
58
+
59
+ module.exports = ProxyAgent
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "4.8.1",
3
+ "version": "4.9.2",
4
4
  "description": "An HTTP/1.1 client, written from scratch for Node.js",
5
5
  "homepage": "https://undici.nodejs.org",
6
6
  "bugs": {
package/types/client.d.ts CHANGED
@@ -39,6 +39,8 @@ declare namespace Client {
39
39
  strictContentLength?: boolean;
40
40
  /** @deprecated use the connect option instead */
41
41
  tls?: TlsOptions | null;
42
+ /** */
43
+ maxRequestsPerClient?: number;
42
44
  }
43
45
 
44
46
  export interface SocketInfo {
@@ -0,0 +1,17 @@
1
+ import Agent = require('./agent')
2
+ import Dispatcher = require('./dispatcher')
3
+
4
+ export = ProxyAgent
5
+
6
+ declare class ProxyAgent extends Dispatcher {
7
+ constructor(options: ProxyAgent.Options | string)
8
+
9
+ dispatch(options: Agent.DispatchOptions, handler: Dispatcher.DispatchHandlers): void;
10
+ close(): Promise<void>;
11
+ }
12
+
13
+ declare namespace ProxyAgent {
14
+ export interface Options extends Agent.Options {
15
+ uri: string;
16
+ }
17
+ }