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

feat: recursive dnslink lookups #1935

Merged
merged 6 commits into from
Apr 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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