1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
'use strict'
const { kProxy, kClose, kDestroy } = require('./core/symbols')
const { URL } = require('url')
const Agent = require('./agent')
const DispatcherBase = require('./dispatcher-base')
const { InvalidArgumentError } = require('./core/errors')
const kAgent = Symbol('proxy agent')
class ProxyAgent extends DispatcherBase {
constructor (opts) {
super(opts)
this[kProxy] = buildProxyOptions(opts)
this[kAgent] = new Agent(opts)
}
dispatch (opts, handler) {
const { host } = new URL(opts.origin)
return this[kAgent].dispatch(
{
...opts,
origin: this[kProxy].uri,
path: opts.origin + opts.path,
headers: {
...buildHeaders(opts.headers),
host
}
},
handler
)
}
async [kClose] () {
await this[kAgent].close()
}
async [kDestroy] () {
await this[kAgent].destroy()
}
}
function buildProxyOptions (opts) {
if (typeof opts === 'string') {
opts = { uri: opts }
}
if (!opts || !opts.uri) {
throw new InvalidArgumentError('Proxy opts.uri is mandatory')
}
return {
uri: opts.uri,
protocol: opts.protocol || 'https'
}
}
/**
* @param {string[] | Record<string, string>} headers
* @returns {Record<string, string>}
*/
function buildHeaders (headers) {
// When using undici.fetch, the headers list is stored
// as an array.
if (Array.isArray(headers)) {
/** @type {Record<string, string>} */
const headersPair = {}
for (let i = 0; i < headers.length; i += 2) {
headersPair[headers[i]] = headers[i + 1]
}
return headersPair
}
return headers
}
module.exports = ProxyAgent
|