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

Commit 8645c3e

Browse files
committed
feat: /api/v0/dns
1 parent 624cb47 commit 8645c3e

File tree

16 files changed

+199
-1
lines changed

16 files changed

+199
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,4 @@ test/test-data/go-ipfs-repo/LOG.old
4040

4141
# while testing npm5
4242
package-lock.json
43+
yarn.lock

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"./src/core/runtime/config-nodejs.json": "./src/core/runtime/config-browser.json",
1212
"./src/core/runtime/libp2p-nodejs.js": "./src/core/runtime/libp2p-browser.js",
1313
"./src/core/runtime/repo-nodejs.js": "./src/core/runtime/repo-browser.js",
14+
"./src/core/runtime/dns-nodejs.js": "./src/core/runtime/dns-browser.js",
1415
"./test/utils/create-repo-nodejs.js": "./test/utils/create-repo-browser.js",
1516
"stream": "readable-stream"
1617
},

src/cli/commands/dns.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict'
2+
const print = require('../utils').print
3+
4+
module.exports = {
5+
command: 'dns <domain>',
6+
7+
describe: 'Resolve DNS links',
8+
9+
builder: {
10+
format: {
11+
type: 'string'
12+
}
13+
},
14+
15+
handler (argv) {
16+
argv.ipfs.dns(argv['domain'], (err, path) => {
17+
if (err) {
18+
throw err
19+
}
20+
21+
print(path)
22+
})
23+
}
24+
}

src/core/components/dns.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
'use strict'
2+
3+
// dns-nodejs gets replaced by dns-browser when webpacked/browserified
4+
const dns = require('../runtime/dns-nodejs')
5+
const promisify = require('promisify-es6')
6+
7+
module.exports = () => {
8+
return promisify((domain, opts, callback) => {
9+
if (typeof domain !== 'string') {
10+
return callback(new Error('Invalid arguments, domain must be a string'))
11+
}
12+
13+
if (typeof opts === 'function') {
14+
callback = opts
15+
opts = {}
16+
}
17+
18+
dns(domain, opts, callback)
19+
})
20+
}

src/core/components/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ exports.files = require('./files')
2020
exports.bitswap = require('./bitswap')
2121
exports.pubsub = require('./pubsub')
2222
exports.dht = require('./dht')
23+
exports.dns = require('./dns')

src/core/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class IPFS extends EventEmitter {
9494
this.ping = components.ping(this)
9595
this.pubsub = components.pubsub(this)
9696
this.dht = components.dht(this)
97+
this.dns = components.dns(this)
9798

9899
if (this._options.EXPERIMENTAL.pubsub) {
99100
this.log('EXPERIMENTAL pubsub is enabled')

src/core/runtime/dns-browser.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict'
2+
3+
module.exports = (domain, opts, callback) => {
4+
domain = encodeURIComponent(domain)
5+
let url = `https://ipfs.io/api/v0/dns?arg=${domain}`
6+
7+
for (const prop in opts) {
8+
url += `&${prop}=${opts[prop]}`
9+
}
10+
11+
window.fetch(url, {mode: 'cors'})
12+
.then((response) => {
13+
return response.json()
14+
})
15+
.then((response) => {
16+
if (response.Path) {
17+
return callback(null, response.Path)
18+
} else {
19+
return callback(new Error(response.Message))
20+
}
21+
})
22+
.catch((error) => {
23+
callback(error)
24+
})
25+
}

src/core/runtime/dns-nodejs.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use strict'
2+
3+
const dns = require('dns')
4+
5+
module.exports = (domain, opts, callback) => {
6+
dns.resolveTxt(domain, (err, records) => {
7+
if (err) {
8+
return callback(err, null)
9+
}
10+
11+
// TODO: implement recursive option
12+
13+
for (const record of records) {
14+
if (record[0].startsWith('dnslink=')) {
15+
return callback(null, record[0].substr(8, record[0].length - 1))
16+
}
17+
}
18+
19+
callback(new Error('domain does not have a txt dnslink entry'))
20+
})
21+
}

src/http/api/resources/dns.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict'
2+
3+
const boom = require('boom')
4+
5+
exports = module.exports
6+
7+
exports.get = (request, reply) => {
8+
if (!request.query.arg) {
9+
return reply({
10+
Message: "Argument 'domain' is required",
11+
Code: 0
12+
}).code(400).takeover()
13+
}
14+
15+
request.server.app.ipfs.dns(request.query.arg, (err, path) => {
16+
if (err) {
17+
return reply(boom.badRequest(err))
18+
}
19+
20+
return reply({
21+
Path: path
22+
})
23+
})
24+
}

src/http/api/resources/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ exports.bitswap = require('./bitswap')
1212
exports.file = require('./file')
1313
exports.files = require('./files')
1414
exports.pubsub = require('./pubsub')
15+
exports.dns = require('./dns')

src/http/api/routes/dns.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict'
2+
3+
const resources = require('./../resources')
4+
5+
module.exports = (server) => {
6+
const api = server.select('API')
7+
8+
api.route({
9+
method: '*',
10+
path: '/api/v0/dns',
11+
handler: resources.dns.get
12+
})
13+
}

src/http/api/routes/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ module.exports = (server) => {
1515
require('./pubsub')(server)
1616
require('./debug')(server)
1717
require('./webui')(server)
18+
require('./dns')(server)
1819
}

test/cli/commands.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
const expect = require('chai').expect
55
const runOnAndOff = require('../utils/on-and-off')
66

7-
const commandCount = 59
7+
const commandCount = 60
88

99
describe('commands', () => runOnAndOff((thing) => {
1010
let ipfs

test/cli/dns.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* eslint-env mocha */
2+
'use strict'
3+
4+
const expect = require('chai').expect
5+
const runOnAndOff = require('../utils/on-and-off')
6+
7+
describe('dns', () => runOnAndOff((thing) => {
8+
let ipfs
9+
10+
before(function () {
11+
this.timeout(60 * 1000)
12+
ipfs = thing.ipfs
13+
})
14+
15+
it('dns record for ipfs.io', function () {
16+
this.timeout(60 * 1000)
17+
18+
return ipfs('ipfs.io').then((res) => {
19+
expect(res.substr(0, 6)).to.eql('/ipfs/')
20+
})
21+
})
22+
}))

test/http-api/extra/dns.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/* eslint-env mocha */
2+
'use strict'
3+
4+
const chai = require('chai')
5+
const dirtyChai = require('dirty-chai')
6+
const expect = chai.expect
7+
chai.use(dirtyChai)
8+
9+
module.exports = (ctl) => {
10+
describe('.dns', () => {
11+
it('get dns for ipfs.io', (done) => {
12+
ctl.dns('ipfs.io', (err, result) => {
13+
expect(err).to.not.exist()
14+
expect(result).to.exist()
15+
done()
16+
})
17+
})
18+
})
19+
}

test/http-api/spec/dns.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* eslint-env mocha */
2+
'use strict'
3+
4+
const expect = require('chai').expect
5+
6+
module.exports = (http) => {
7+
describe('/dns', () => {
8+
let api
9+
10+
before(() => {
11+
api = http.api.server.select('API')
12+
})
13+
14+
it('get the id', (done) => {
15+
api.inject({
16+
method: 'GET',
17+
url: '/api/v0/dns?arg=ipfs.io'
18+
}, (res) => {
19+
expect(res).to.have.property('Path')
20+
done()
21+
})
22+
})
23+
})
24+
}

0 commit comments

Comments
 (0)