diff --git a/src/core/runtime/dns-nodejs.js b/src/core/runtime/dns-nodejs.js index 8f6bb132bd..a3d583ef92 100644 --- a/src/core/runtime/dns-nodejs.js +++ b/src/core/runtime/dns-nodejs.js @@ -1,21 +1,51 @@ 'use strict' const dns = require('dns') +const _ = require('lodash') +const errcode = require('err-code') module.exports = (domain, opts, callback) => { - dns.resolveTxt(domain, (err, records) => { - if (err) { - return callback(err, null) - } + resolveDnslink(domain) + .catch(err => { + // If the code is not ENOTFOUND or ERR_DNSLINK_NOT_FOUND then throw the error + if (err.code !== 'ENOTFOUND' && err.code !== 'ERR_DNSLINK_NOT_FOUND') throw err - // TODO: implement recursive option - - for (const record of records) { - if (record[0].startsWith('dnslink=')) { - return callback(null, record[0].substr(8, record[0].length - 1)) + if (domain.startsWith('_dnslink.')) { + // The supplied domain contains a _dnslink component + // Check the non-_dnslink domain + const rootDomain = domain.replace('_dnslink.', '') + return resolveDnslink(rootDomain) } - } + // Check the _dnslink subdomain + const _dnslinkDomain = `_dnslink.${domain}` + // If this throws then we propagate the error + return resolveDnslink(_dnslinkDomain) + }) + .then(dnslinkRecord => { + callback(null, dnslinkRecord.replace('dnslink=', '')) + }) + .catch(callback) +} - callback(new Error('domain does not have a txt dnslink entry')) +function resolveDnslink (domain) { + const DNSLINK_REGEX = /^dnslink=.+$/ + return new Promise((resolve, reject) => { + dns.resolveTxt(domain, (err, records) => { + if (err) return reject(err) + resolve(records) + }) }) + .then(records => { + return _.chain(records).flatten().filter(record => { + return DNSLINK_REGEX.test(record) + }).value() + }) + .then(dnslinkRecords => { + // 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(`No dnslink records found for domain: ${domain}`, 'ERR_DNSLINK_NOT_FOUND') + } + return dnslinkRecords[0] + }) } diff --git a/test/cli/dns.js b/test/cli/dns.js index 0c6ab4e1a5..55aea6f5b6 100644 --- a/test/cli/dns.js +++ b/test/cli/dns.js @@ -19,4 +19,12 @@ describe('dns', () => runOnAndOff((thing) => { expect(res.substr(0, 6)).to.eql('/ipns/') }) }) + + it('resolve _dnslink.ipfs.io dns', function () { + this.timeout(60 * 1000) + + return ipfs('dns _dnslink.ipfs.io').then((res) => { + expect(res.substr(0, 6)).to.eql('/ipns/') + }) + }) }))