Skip to content

Commit 4901718

Browse files
hugomrdiaslidel
authored andcommitted
feat: add support to ipns resolve /ipns/<fqdn>
fixes: ipfs#1918
1 parent 752e904 commit 4901718

File tree

5 files changed

+94
-22
lines changed

5 files changed

+94
-22
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
"ipld-raw": "^2.0.1",
130130
"ipld-zcash": "~0.1.6",
131131
"ipns": "~0.5.0",
132+
"is-domain-name": "^1.0.1",
132133
"is-ipfs": "~0.6.0",
133134
"is-pull-stream": "~0.0.0",
134135
"is-stream": "^1.1.0",

src/core/components/name.js

+38-17
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ const parallel = require('async/parallel')
77
const human = require('human-to-milliseconds')
88
const crypto = require('libp2p-crypto')
99
const errcode = require('err-code')
10+
const mergeOptions = require('merge-options')
11+
const mh = require('multihashes')
12+
const isDomain = require('is-domain-name')
1013

1114
const log = debug('ipfs:name')
1215
log.error = debug('ipfs:name:error')
@@ -35,6 +38,16 @@ const keyLookup = (ipfsNode, kname, callback) => {
3538
})
3639
}
3740

41+
/**
42+
* @typedef { import("../index") } IPFS
43+
*/
44+
45+
/**
46+
* IPNS - Inter-Planetary Naming System
47+
*
48+
* @param {IPFS} self
49+
* @returns {Function}
50+
*/
3851
module.exports = function name (self) {
3952
return {
4053
/**
@@ -125,22 +138,15 @@ module.exports = function name (self) {
125138
options = {}
126139
}
127140

128-
options = options || {}
129-
const nocache = options.nocache && options.nocache.toString() === 'true'
130-
const recursive = options.recursive && options.recursive.toString() === 'true'
141+
options = mergeOptions({
142+
nocache: false,
143+
recursive: false
144+
}, options)
131145

132146
const offline = self._options.offline
133147

134-
if (!self.isOnline() && !offline) {
135-
const errMsg = utils.OFFLINE_ERROR
136-
137-
log.error(errMsg)
138-
return callback(errcode(errMsg, 'OFFLINE_ERROR'))
139-
}
140-
141148
// TODO: params related logic should be in the core implementation
142-
143-
if (offline && nocache) {
149+
if (offline && options.nocache) {
144150
const error = 'cannot specify both offline and nocache'
145151

146152
log.error(error)
@@ -156,12 +162,27 @@ module.exports = function name (self) {
156162
name = `/ipns/${name}`
157163
}
158164

159-
const resolveOptions = {
160-
nocache,
161-
recursive
162-
}
165+
const [ , hash ] = name.slice(1).split('/')
166+
try {
167+
mh.fromB58String(hash)
168+
169+
// ipns resolve needs a online daemon
170+
if (!self.isOnline() && !offline) {
171+
const errMsg = utils.OFFLINE_ERROR
163172

164-
self._ipns.resolve(name, resolveOptions, callback)
173+
log.error(errMsg)
174+
return callback(errcode(errMsg, 'OFFLINE_ERROR'))
175+
}
176+
self._ipns.resolve(name, options, callback)
177+
} catch (err) {
178+
// lets check if we have a domain ex. /ipns/ipfs.io and resolve with dns
179+
if (isDomain(hash)) {
180+
return self.dns(hash, options, callback)
181+
}
182+
183+
log.error(err)
184+
callback(errcode(new Error('Invalid IPNS name.'), 'ERR_IPNS_INVALID_NAME'))
185+
}
165186
}),
166187
pubsub: namePubsub(self)
167188
}

src/core/index.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,16 @@ const defaultRepo = require('./runtime/repo-nodejs')
2626
const preload = require('./preload')
2727
const mfsPreload = require('./mfs-preload')
2828
const ipldOptions = require('./runtime/ipld-nodejs')
29-
29+
/**
30+
* @typedef { import("./ipns/index") } IPNS
31+
*/
32+
33+
/**
34+
*
35+
*
36+
* @class IPFS
37+
* @extends {EventEmitter}
38+
*/
3039
class IPFS extends EventEmitter {
3140
constructor (options) {
3241
super()
@@ -76,6 +85,7 @@ class IPFS extends EventEmitter {
7685
this._ipld = new Ipld(ipldOptions(this._blockService, this._options.ipld, this.log))
7786
this._preload = preload(this)
7887
this._mfsPreload = mfsPreload(this)
88+
/** @type {IPNS} */
7989
this._ipns = undefined
8090
// eslint-disable-next-line no-console
8191
this._print = this._options.silent ? this.log : console.log

src/core/ipns/index.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -104,5 +104,6 @@ class IPNS {
104104
}
105105
}
106106

107-
exports = module.exports = IPNS
108-
exports.path = path
107+
IPNS.path = path
108+
109+
module.exports = IPNS

test/core/name.js

+41-2
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ describe('name', function () {
123123
})
124124
})
125125

126-
it('should not recursively resolve to an IPFS hash if the option recursive is not provided', function (done) {
126+
it('should not recursively resolve to an IPFS hash', function (done) {
127127
this.timeout(90 * 1000)
128128
const keyName = hat()
129129

@@ -132,7 +132,7 @@ describe('name', function () {
132132
series([
133133
(cb) => node.name.publish(ipfsRef, { resolve: false }, cb),
134134
(cb) => node.name.publish(`/ipns/${nodeId}`, { resolve: false, key: keyName }, cb),
135-
(cb) => node.name.resolve(key.id, cb)
135+
(cb) => node.name.resolve(key.id, { recursive: false }, cb)
136136
], (err, res) => {
137137
expect(err).to.not.exist()
138138
expect(res[2]).to.exist()
@@ -618,4 +618,43 @@ describe('name', function () {
618618
done()
619619
})
620620
})
621+
622+
describe('working with dns', function () {
623+
let node
624+
let ipfsd
625+
626+
before(function (done) {
627+
df.spawn({
628+
exec: IPFS,
629+
args: [`--pass ${hat()}`, '--offline'],
630+
config: { Bootstrap: [] }
631+
}, (err, _ipfsd) => {
632+
expect(err).to.not.exist()
633+
ipfsd = _ipfsd
634+
node = _ipfsd.api
635+
done()
636+
})
637+
})
638+
639+
after((done) => ipfsd.stop(done))
640+
641+
it('should resolve ipfs.io', async () => {
642+
const r = await node.name.resolve('ipfs.io', { recursive: false })
643+
return expect(r).to.eq('/ipns/website.ipfs.io')
644+
})
645+
646+
it('should resolve /ipns/ipfs.io recursive', async () => {
647+
const r = await node.name.resolve('ipfs.io', { recursive: true })
648+
649+
return expect(r.substr(0, 6)).to.eql('/ipfs/')
650+
})
651+
652+
it('should fail to resolve /ipns/ipfs.a', async () => {
653+
try {
654+
await node.name.resolve('ipfs.a')
655+
} catch (err) {
656+
expect(err).to.exist()
657+
}
658+
})
659+
})
621660
})

0 commit comments

Comments
 (0)