Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

Commit

Permalink
feat: recursive dnslink lookups (#1935)
Browse files Browse the repository at this point in the history
Co-Authored-By: niinpatel <31539366+niinpatel@users.noreply.github.com>
  • Loading branch information
niinpatel authored and Alan Shaw committed Apr 8, 2019
1 parent 20beea2 commit d5a1b89
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 9 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@ The core API is grouped into several areas:
- [`ipfs.stop([callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/MISCELLANEOUS.md#stop)
- `ipfs.isOnline()`
- [`ipfs.resolve(name, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/MISCELLANEOUS.md#resolve)
- [`ipfs.dns(name, [options], [callback]`](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#dns)
- [repo](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/REPO.md)
- `ipfs.repo.init`
Expand Down
10 changes: 8 additions & 2 deletions src/cli/commands/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ module.exports = {
describe: 'Resolve DNS links',

builder: {
recursive: {
type: 'boolean',
default: true,
alias: 'r',
desc: 'Resolve until the result is not a DNS link'
},
format: {
type: 'string'
}
},

handler ({ getIpfs, domain, resolve }) {
handler ({ getIpfs, domain, resolve, recursive, format }) {
resolve((async () => {
const ipfs = await getIpfs()
const path = await ipfs.dns(domain)
const path = await ipfs.dns(domain, { recursive, format })
print(path)
})())
}
Expand Down
30 changes: 28 additions & 2 deletions src/core/runtime/dns-nodejs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,29 @@

const dns = require('dns')
const _ = require('lodash')
const isIPFS = require('is-ipfs')
const errcode = require('err-code')

const MAX_RECURSIVE_DEPTH = 32

module.exports = (domain, opts, callback) => {
resolveDnslink(domain)
// 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, callback)
}

function recursiveResolveDnslink (domain, depth, callback) {
if (depth === 0) {
return callback(errcode(`recursion limit exceeded`, 'ERR_DNSLINK_RECURSION_LIMIT'))
}

return 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
Expand All @@ -22,7 +41,14 @@ module.exports = (domain, opts, callback) => {
return resolveDnslink(_dnslinkDomain)
})
.then(dnslinkRecord => {
callback(null, dnslinkRecord.replace('dnslink=', ''))
const result = dnslinkRecord.replace('dnslink=', '')
const domainOrCID = result.split('/')[2]
const isIPFSCID = isIPFS.cid(domainOrCID)

if (isIPFSCID || !depth) {
return callback(null, result)
}
return recursiveResolveDnslink(domainOrCID, depth - 1, callback)
})
.catch(callback)
}
Expand Down
12 changes: 10 additions & 2 deletions src/http/api/resources/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@
const Boom = require('boom')

module.exports = async (request, h) => {
if (!request.query.arg) {
const domain = request.query.arg

if (!domain) {
throw Boom.badRequest("Argument 'domain' is required")
}

const path = await request.server.app.ipfs.dns(request.query.arg)
const format = request.query.format

// query parameters are passed as strings and need to be parsed to expected type
let recursive = request.query.recursive || request.query.r
recursive = !(recursive && recursive === 'false')

const path = await request.server.app.ipfs.dns(domain, { recursive, format })
return h.response({
Path: path
})
Expand Down
21 changes: 18 additions & 3 deletions test/cli/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

const expect = require('chai').expect
const runOnAndOff = require('../utils/on-and-off')
const isIPFS = require('is-ipfs')

describe('dns', () => runOnAndOff((thing) => {
let ipfs
Expand All @@ -12,19 +13,33 @@ describe('dns', () => runOnAndOff((thing) => {
ipfs = thing.ipfs
})

it('resolve ipfs.io dns', function () {
it('recursively resolve ipfs.io dns', function () {
this.timeout(60 * 1000)

return ipfs('dns ipfs.io').then((res) => {
expect(res.substr(0, 6)).to.eql('/ipns/')
expect(res.substr(0, 6)).to.eql('/ipfs/')
const resultingDomainOrCid = res.split('/')[2].trim()
expect(isIPFS.cid(resultingDomainOrCid)).to.eql(true)
})
})

it('resolve _dnslink.ipfs.io dns', function () {
it('recursively 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('/ipfs/')
const resultingDomainOrCid = res.split('/')[2].trim()
expect(isIPFS.cid(resultingDomainOrCid)).to.eql(true)
})
})

it('non-recursive resolve ipfs.io', function () {
this.timeout(60 * 1000)

return ipfs('dns --recursive false ipfs.io').then((res) => {
expect(res.substr(0, 6)).to.eql('/ipns/')
const resultingDomainOrCid = res.split('/')[2].trim()
expect(isIPFS.cid(resultingDomainOrCid)).to.eql(false)
})
})

Expand Down

0 comments on commit d5a1b89

Please sign in to comment.