This repository has been archived by the owner on Dec 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.js
88 lines (78 loc) · 2.14 KB
/
index.js
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
80
81
82
83
84
85
86
87
88
'use strict'
const { DOHClient } = require('dns2')
const loggerNoop = (() => {
const debug = () => {}
debug.info = debug
debug.error = debug
return debug
})()
const timestamp = (start = process.hrtime()) => () => {
const hrtime = process.hrtime(start)
const nanoseconds = hrtime[0] * 1e9 + hrtime[1]
return nanoseconds / 1e6
}
const createLogWithDuration = transport => (...args) => {
const end = timestamp()
return () => transport(...args, { duration: `${Math.round(end())}ms` })
}
const logTime = async (fn, props, logWithDuration) => {
const time = logWithDuration(props)
const result = await fn()
time()
return result
}
class DoHResolver {
constructor ({
logger = loggerNoop,
servers,
get,
onError = (cb, error) => cb(error.errors[0])
}) {
this.servers = [].concat(servers)
this.resolve4 = this.createTypeResolver('A')
this.resolve6 = this.createTypeResolver('AAAA')
this.get = get
this.onError = onError
this.log = {
debug: createLogWithDuration(logger),
info: createLogWithDuration(logger.info),
error: logger.error
}
}
getServers = () => this.servers
setServers = servers => (this.servers = [...servers])
createTypeResolver = type => {
return async function (domain, options, cb) {
const clients = this.servers.map(dns => DOHClient({ dns, get: this.get }))
try {
cb(
null,
await logTime(
() =>
Promise.any(
clients.map((client, index) =>
logTime(
() => client(domain, type).then(({ answers }) => answers),
{
server: this.servers[index],
type,
domain
},
this.log.debug
)
)
),
{ type, domain },
this.log.info
)
)
} catch (error) {
error.errors.forEach(({ name, code, message }) =>
this.log.error({ name, code, message })
)
this.onError(cb, error)
}
}
}
}
module.exports = DoHResolver