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

Commit 180a5e4

Browse files
committed
Merge pull request #69 from ipfs/feature/http-api
WIP: Make http-api endpoints as specified by the http-api-spec, for the features present in core
2 parents 50d95a7 + d169279 commit 180a5e4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+824
-436
lines changed

package.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88
"main": "src/index.js",
99
"scripts": {
1010
"lint": "standard",
11-
"coverage": "istanbul cover --print both -- _mocha tests/test-*/index.js",
11+
"coverage": "istanbul cover --print both -- _mocha tests/test-core/index.js",
1212
"test": "npm run test:node && npm run test:browser",
13-
"test:node": "mocha tests/test-*/index.js",
13+
"test:node": "npm run test:node:core && npm run test:node:http-api && npm run test:node:cli",
14+
"test:node:cli": "mocha tests/test-cli/index.js",
15+
"test:node:core": "mocha tests/test-core/index.js",
16+
"test:node:http-api": "mocha tests/test-http-api/index.js",
1417
"test:browser": "karma start karma.conf.js",
1518
"test:core": "mocha tests/test-core/index.js",
16-
"test:cli": "mocha tests/test-cli/index.js",
17-
"test:cli-offline": "mocha tests/test-cli-offline/index.js"
19+
"test:cli": "mocha tests/test-cli/index.js"
1820
},
1921
"pre-commit": [
2022
"lint",
@@ -67,9 +69,11 @@
6769
"bs58": "^3.0.0",
6870
"debug": "^2.2.0",
6971
"hapi": "^12.0.0",
72+
"ipfs-api": "^2.13.1",
7073
"ipfs-blocks": "^0.1.0",
7174
"ipfs-merkle-dag": "^0.2.1",
7275
"ipfs-repo": "^0.5.0",
76+
"joi": "^8.0.2",
7377
"lodash.get": "^4.0.0",
7478
"lodash.set": "^4.0.0",
7579
"peer-id": "^0.5.0",

src/cli/commands/daemon.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,28 @@ const Command = require('ronin').Command
44
const httpAPI = require('../../http-api')
55
const debug = require('debug')
66
const log = debug('cli:daemon')
7-
log.error = debug('cli:damon:error')
7+
log.error = debug('cli:daemon:error')
88

99
module.exports = Command.extend({
1010
desc: 'Start a long-running daemon process',
1111

1212
run: name => {
13+
console.log('Initializing daemon...')
1314
httpAPI.start((err) => {
14-
if (err) { return log.error(err) }
15-
log('daemon started')
15+
if (err) {
16+
return log.error(err)
17+
}
18+
console.log('Daemon is ready')
19+
})
20+
21+
process.on('SIGINT', () => {
22+
console.log('Received interrupt signal, shutting down..')
23+
httpAPI.stop((err) => {
24+
if (err) {
25+
return log.error(err)
26+
}
27+
process.exit(0)
28+
})
1629
})
1730
}
1831
})

src/cli/commands/id.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
const Command = require('ronin').Command
22
const IPFS = require('../../ipfs-core')
33
const debug = require('debug')
4-
const log = debug('cli:id')
5-
log.error = debug('cli:id:error')
4+
const utils = require('../utils')
5+
const log = debug('cli')
6+
log.error = debug('cli:error')
67

78
module.exports = Command.extend({
89
desc: 'Shows IPFS Node ID info',
@@ -14,11 +15,23 @@ module.exports = Command.extend({
1415
}
1516
},
1617

17-
run: name => {
18-
const node = new IPFS()
19-
node.id((err, id) => {
20-
if (err) { return log.error(err) }
21-
console.log(id)
22-
})
18+
run: (name) => {
19+
if (utils.isDaemonOn()) {
20+
const ctl = utils.getAPICtl()
21+
ctl.id((err, result) => {
22+
if (err) {
23+
return log.error(err)
24+
}
25+
console.log(result)
26+
})
27+
} else {
28+
const node = new IPFS()
29+
node.id((err, id) => {
30+
if (err) {
31+
return log.error(err)
32+
}
33+
console.log(id)
34+
})
35+
}
2336
}
2437
})

src/cli/utils.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const fs = require('fs')
2+
const os = require('os')
3+
const APIctl = require('ipfs-api')
4+
const multiaddr = require('multiaddr')
5+
const debug = require('debug')
6+
const log = debug('cli')
7+
log.error = debug('cli:error')
8+
9+
exports = module.exports
10+
11+
const repoPath = process.env.IPFS_PATH || os.homedir() + '/.ipfs'
12+
13+
exports.isDaemonOn = isDaemonOn
14+
function isDaemonOn () {
15+
try {
16+
fs.readFileSync(repoPath + '/api')
17+
log('daemon is on')
18+
return true
19+
} catch (err) {
20+
log('daemon is off')
21+
return false
22+
}
23+
}
24+
25+
exports.getAPICtl = () => {
26+
if (!isDaemonOn) {
27+
throw new Error('daemon is not on')
28+
}
29+
30+
const apiAddr = multiaddr(fs.readFileSync(repoPath + '/api').toString())
31+
return APIctl(apiAddr.toString())
32+
}

src/help-menu.js

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/http-api/index.js

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,66 @@
33
const Hapi = require('hapi')
44
const IPFS = require('../ipfs-core')
55
const debug = require('debug')
6+
const fs = require('fs')
7+
const os = require('os')
68
const log = debug('api')
79
log.error = debug('api:error')
810

911
exports = module.exports
1012

11-
exports.start = callback => {
12-
// start IPFS and exports.ipfs = new IPFS()
13+
exports.start = (callback) => {
14+
const ipfs = exports.ipfs = new IPFS()
1315

14-
exports.ipfs = new IPFS()
16+
const repoPath = process.env.IPFS_PATH || os.homedir() + '/.ipfs'
17+
try {
18+
fs.statSync(repoPath + '/api')
19+
console.log('This repo is currently being used by another daemon')
20+
process.exit(1)
21+
} catch (err) {
22+
fs.writeFileSync(repoPath + '/api', 'api is on by js-ipfs', {flag: 'w+'})
23+
}
1524

16-
var server = exports.server = new Hapi.Server({
17-
connections: {
18-
routes: {
19-
cors: true
20-
}
25+
ipfs.config.show((err, config) => {
26+
if (err) {
27+
return callback(err)
2128
}
22-
})
2329

24-
server.connection({
25-
port: 9001
26-
})
30+
// TODO: set up cors correctly, following config
31+
var server = exports.server = new Hapi.Server({
32+
connections: {
33+
routes: {
34+
cors: true
35+
}
36+
}
37+
})
38+
const api = config.Addresses.API.split('/')
39+
const gateway = config.Addresses.Gateway.split('/')
2740

28-
// load routes
29-
require('./routes')
41+
// for the CLI to know the where abouts of the API
42+
fs.writeFileSync(repoPath + '/api', config.Addresses.API)
3043

31-
server.start(err => {
32-
if (err) { return callback(err) }
33-
log('server started: ' + server.info.uri)
34-
callback()
44+
// select which connection with server.select(<label>) to add routes
45+
server.connection({ host: api[2], port: api[4], labels: 'API' })
46+
server.connection({ host: gateway[2], port: gateway[4], labels: 'Gateway' })
47+
48+
// load routes
49+
require('./routes')
50+
51+
server.start((err) => {
52+
if (err) {
53+
return callback(err)
54+
}
55+
const api = server.select('API')
56+
const gateway = server.select('Gateway')
57+
console.log('API is listening on: ' + api.info.uri)
58+
console.log('Gateway (readonly) is listening on: ' + gateway.info.uri)
59+
callback()
60+
})
3561
})
3662
}
3763

3864
exports.stop = callback => {
65+
const repoPath = process.env.IPFS_PATH || os.homedir() + '/.ipfs'
66+
fs.unlinkSync(repoPath + '/api')
3967
exports.server.stop(callback)
4068
}

src/http-api/resources/block.js

Whitespace-only changes.

src/http-api/resources/bootstrap.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const ipfs = require('./../index.js').ipfs
2+
const boom = require('boom')
3+
4+
exports = module.exports
5+
6+
exports.list = (request, reply) => {
7+
ipfs.bootstrap.list((err, list) => {
8+
if (err) {
9+
return reply(boom.badRequest(err))
10+
}
11+
return reply(list)
12+
})
13+
}
14+
15+
exports.add = (request, reply) => {
16+
// ipfs.id((err, id) => {
17+
// if (err) { return reply(boom.badRequest(err)) }
18+
// return reply(id)
19+
// })
20+
}
21+
22+
exports.rm = (request, reply) => {
23+
// ipfs.id((err, id) => {
24+
// if (err) { return reply(boom.badRequest(err)) }
25+
// return reply(id)
26+
// })
27+
}

src/http-api/resources/config.js

Whitespace-only changes.

src/http-api/resources/id.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
'use strict'
2-
31
const ipfs = require('./../index.js').ipfs
42
const boom = require('boom')
53

src/http-api/resources/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
exports.version = require('./version')
22
exports.id = require('./id')
3+
exports.bootstrap = require('./bootstrap')
4+
exports.repo = require('./repo')
5+
exports.object = require('./object')
6+
exports.config = require('./config')
7+
exports.block = require('./block')

src/http-api/resources/object.js

Whitespace-only changes.

src/http-api/resources/repo.js

Whitespace-only changes.

src/http-api/resources/version.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
1-
'use strict'
2-
31
const ipfs = require('./../index.js').ipfs
42
const boom = require('boom')
53

64
exports = module.exports
75

86
exports.get = (request, reply) => {
9-
ipfs.version((err, version) => {
10-
if (err) { return reply(boom.badRequest(err)) }
11-
return reply(version)
7+
ipfs.version((err, ipfsVersion) => {
8+
if (err) {
9+
return reply(boom.badRequest(err))
10+
}
11+
12+
ipfs.repo.version((err, repoVersion) => {
13+
if (err) {
14+
return reply(boom.badRequest(err))
15+
}
16+
17+
console.log('--------->')
18+
19+
reply({
20+
Version: ipfsVersion,
21+
Commit: '',
22+
Repo: repoVersion
23+
}).header('Transfer-Encoding', 'chunked')
24+
// .header('Trailer', 'X-Stream-Error')
25+
.type('application/json')
26+
})
1227
})
1328
}

src/http-api/routes/block.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const api = require('./../index.js').server.select('API')
2+
const resources = require('./../resources')
3+
4+
// TODO
5+
6+
api.route({
7+
method: 'GET',
8+
path: '/api/v0/block',
9+
handler: resources.block
10+
})

src/http-api/routes/bootstrap.js

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,47 @@
1-
'use strict'
2-
3-
const server = require('./../index.js').server
1+
const api = require('./../index.js').server.select('API')
42
const resources = require('./../resources')
3+
const Joi = require('joi')
54

6-
server.route({
5+
// https://github.com/ipfs/http-api-spec/blob/master/apiary.apib#L818
6+
api.route({
77
method: 'GET',
88
path: '/api/v0/bootstrap',
9-
handler: resources.version.list
9+
handler: resources.bootstrap.list
1010
})
1111

12-
server.route({
13-
method: 'POST',
14-
path: '/api/v0/bootstrap',
15-
handler: resources.version.add
12+
// https://github.com/ipfs/http-api-spec/blob/master/apiary.apib#L866
13+
api.route({
14+
method: 'GET',
15+
path: '/api/v0/bootstrap/add',
16+
handler: resources.bootstrap.add,
17+
config: {
18+
validate: {
19+
query: {
20+
arg: Joi.string().required(), // multiaddr to add
21+
default: Joi.boolean()
22+
}
23+
}
24+
}
1625
})
1726

18-
server.route({
19-
method: 'DELETE',
20-
path: '/api/v0/bootstrap',
21-
handler: resources.version.add
27+
// https://github.com/ipfs/http-api-spec/blob/master/apiary.apib#L1081
28+
api.route({
29+
method: 'GET',
30+
path: '/api/v0/bootstrap/list',
31+
handler: resources.bootstrap.list
32+
})
33+
34+
// https://github.com/ipfs/http-api-spec/blob/master/apiary.apib#L1131
35+
api.route({
36+
method: 'GET',
37+
path: '/api/v0/bootstrap/rm',
38+
handler: resources.bootstrap.rm,
39+
config: {
40+
validate: {
41+
query: {
42+
arg: Joi.string().required(), // multiaddr to rm
43+
all: Joi.boolean()
44+
}
45+
}
46+
}
2247
})

src/http-api/routes/config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const api = require('./../index.js').server.select('API')
2+
const resources = require('./../resources')
3+
4+
// TODO
5+
6+
api.route({
7+
method: 'GET',
8+
path: '/api/v0/config',
9+
handler: resources.config
10+
})

0 commit comments

Comments
 (0)