This repository has been archived by the owner on Feb 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
dns-nodejs.js
74 lines (59 loc) · 2.21 KB
/
dns-nodejs.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
'use strict'
const dns = require('dns')
const flatten = require('lodash.flatten')
const isIPFS = require('is-ipfs')
const errcode = require('err-code')
const promisify = require('promisify-es6')
const MAX_RECURSIVE_DEPTH = 32
module.exports = (domain, opts) => {
// recursive is true by default, it's set to false only if explicitly passed as argument in opts
const recursive = opts.recursive == null ? true : Boolean(opts.recursive)
let depth
if (recursive) {
depth = MAX_RECURSIVE_DEPTH
}
return recursiveResolveDnslink(domain, depth)
}
async function recursiveResolveDnslink (domain, depth) {
if (depth === 0) {
throw errcode(new Error('recursion limit exceeded'), 'ERR_DNSLINK_RECURSION_LIMIT')
}
let dnslinkRecord
try {
dnslinkRecord = await resolveDnslink(domain)
} catch (err) {
// If the code is not ENOTFOUND or ERR_DNSLINK_NOT_FOUND or ENODATA then throw the error
if (err.code !== 'ENOTFOUND' && err.code !== 'ERR_DNSLINK_NOT_FOUND' && err.code !== 'ENODATA') {
throw err
}
if (domain.startsWith('_dnslink.')) {
// The supplied domain contains a _dnslink component
// Check the non-_dnslink domain
dnslinkRecord = await resolveDnslink(domain.replace('_dnslink.', ''))
} else {
// Check the _dnslink subdomain
const _dnslinkDomain = `_dnslink.${domain}`
// If this throws then we propagate the error
dnslinkRecord = await resolveDnslink(_dnslinkDomain)
}
}
const result = dnslinkRecord.replace('dnslink=', '')
const domainOrCID = result.split('/')[2]
const isIPFSCID = isIPFS.cid(domainOrCID)
if (isIPFSCID || !depth) {
return result
}
return recursiveResolveDnslink(domainOrCID, depth - 1)
}
async function resolveDnslink (domain) {
const DNSLINK_REGEX = /^dnslink=.+$/
const records = await promisify(dns.resolveTxt)(domain)
const dnslinkRecords = flatten(records)
.filter(record => DNSLINK_REGEX.test(record))
// we now have dns text entries as an array of strings
// only records passing the DNSLINK_REGEX text are included
if (dnslinkRecords.length === 0) {
throw errcode(new Error(`No dnslink records found for domain: ${domain}`), 'ERR_DNSLINK_NOT_FOUND')
}
return dnslinkRecords[0]
}