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

jsipfs block http-api and cli #81

Merged
merged 3 commits into from
Apr 2, 2016
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
**/node_modules/
**/*.log
tests/repo-tests*
test/repo-tests*

# Logs
logs
Expand Down
42 changes: 42 additions & 0 deletions src/cli/commands/block/get.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const Command = require('ronin').Command
const utils = require('../../utils')
const bs58 = require('bs58')
const debug = require('debug')
const log = debug('cli:block')
log.error = debug('cli:block:error')

module.exports = Command.extend({
desc: 'Get a raw IPFS block',

options: {},

run: (key) => {
if (!key) {
throw new Error("Argument 'key' is required")
}

utils.getIPFS((err, ipfs) => {
if (err) {
throw err
}

const mh = utils.isDaemonOn()
? key
: new Buffer(bs58.decode(key))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

soon all these hacks will be gone (once we get core spec \o/)


ipfs.block.get(mh, (err, block) => {
if (err) {
log.error(err)
throw err
}

if (block.data) {
console.log(block.data.toString())
return
}

console.log(block.toString())
})
})
}
})
60 changes: 60 additions & 0 deletions src/cli/commands/block/put.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const Command = require('ronin').Command
const utils = require('../../utils')
const bs58 = require('bs58')
const bl = require('bl')
const fs = require('fs')
const Block = require('ipfs-blocks').Block
const debug = require('debug')
const log = debug('cli:block')
log.error = debug('cli:block:error')

function addBlock (buf) {
utils.getIPFS((err, ipfs) => {
if (err) {
throw err
}

if (utils.isDaemonOn()) {
return ipfs.block.put(buf, (err, block) => {
if (err) {
log.error(err)
throw err
}

console.log(block.Key)
})
}

const block = new Block(buf)

ipfs.block.put(block, (err, obj) => {
if (err) {
log.error(err)
throw err
}

console.log(bs58.encode(block.key).toString())
})
})
}

module.exports = Command.extend({
desc: 'Stores input as an IPFS block',

options: {},

run: (filePath) => {
if (filePath) {
return addBlock(fs.readFileSync(filePath))
}

process.stdin.pipe(bl((err, input) => {
if (err) {
log.error(err)
throw err
}

addBlock(input)
}))
}
})
42 changes: 42 additions & 0 deletions src/cli/commands/block/rm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict'

const Command = require('ronin').Command
const utils = require('../../utils')
const bs58 = require('bs58')
const debug = require('debug')
const log = debug('cli:block')
log.error = debug('cli:block:error')

module.exports = Command.extend({
desc: 'Remove a raw IPFS block',

options: {},

run: (key) => {
if (!key) {
throw new Error("Argument 'key' is required")
}

utils.getIPFS((err, ipfs) => {
if (err) {
throw err
}

if (utils.isDaemonOn()) {
// TODO implement this once `js-ipfs-api` supports it
throw new Error('rm block with daemon running is not yet implemented')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? We have 'del', right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no ipfs block del or rm on go-ipfs, so js-ipfs-api doesn't have it either. I could make the raw request here, but thought it would be better to wait and avoid Yet Another Hack™. What are your thoughts on this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good. We definitely need to push it to be part of the spec (go-ipfs can delete things on disk directly, js-ipfs-api has to interact with disk through the blob-store, always)

}

const mh = new Buffer(bs58.decode(key))

ipfs.block.del(mh, (err) => {
if (err) {
log.error(err)
throw err
}

console.log('removed', key)
})
})
}
})
45 changes: 45 additions & 0 deletions src/cli/commands/block/stat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict'

const Command = require('ronin').Command
const utils = require('../../utils')
const bs58 = require('bs58')
const debug = require('debug')
const log = debug('cli:block')
log.error = debug('cli:block:error')

module.exports = Command.extend({
desc: 'Print information of a raw IPFS block',

options: {},

run: (key) => {
if (!key) {
throw new Error("Argument 'key' is required")
}

utils.getIPFS((err, ipfs) => {
if (err) {
throw err
}

const mh = utils.isDaemonOn()
? key
: new Buffer(bs58.decode(key))

ipfs.block.stat(mh, (err, block) => {
if (err) {
log.error(err)
throw err
}

if (typeof block.Key !== 'string') {
block.Key = bs58.encode(block.Key).toString()
}

Object.keys(block).forEach((key) => {
console.log(`${key}: ${block[key]}`)
})
})
})
}
})
149 changes: 149 additions & 0 deletions src/http-api/resources/block.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
'use strict'

const ipfs = require('./../index.js').ipfs
const bs58 = require('bs58')
const multipart = require('ipfs-multipart')
const Block = require('ipfs-blocks').Block
const debug = require('debug')
const log = debug('http-api:block')
log.error = debug('http-api:block:error')

exports = module.exports

// common pre request handler that parses the args and returns `key` which is assigned to `request.pre.args`
exports.parseKey = (request, reply) => {
if (!request.query.arg) {
return reply("Argument 'key' is required").code(400).takeover()
}

try {
return reply({
key: new Buffer(bs58.decode(request.query.arg))
})
} catch (err) {
log.error(err)
return reply({
Message: 'Not a valid hash',
Code: 0
}).code(500).takeover()
}
}

exports.get = {
// uses common parseKey method that returns a `key`
parseArgs: exports.parseKey,

// main route handler which is called after the above `parseArgs`, but only if the args were valid
handler: (request, reply) => {
const key = request.pre.args.key

ipfs.block.get(key, (err, block) => {
if (err) {
log.error(err)
return reply({
Message: 'Failed to get block: ' + err,
Code: 0
}).code(500)
}

return reply(block.data.toString())
})
}
}

exports.put = {
// pre request handler that parses the args and returns `data` which is assigned to `request.pre.args`
parseArgs: (request, reply) => {
if (!request.payload) {
return reply("File argument 'data' is required").code(400).takeover()
}

const parser = multipart.reqParser(request.payload)
var file

parser.on('file', (fileName, fileStream) => {
fileStream.on('data', (data) => {
file = data
})
})

parser.on('end', () => {
if (!file) {
return reply("File argument 'data' is required").code(400).takeover()
}

return reply({
data: file.toString()
})
})
},

// main route handler which is called after the above `parseArgs`, but only if the args were valid
handler: (request, reply) => {
const data = request.pre.args.data

const block = new Block(data)

ipfs.block.put(block, (err) => {
if (err) {
log.error(err)
return reply({
Message: 'Failed to put block: ' + err,
Code: 0
}).code(500)
}

return reply({
Key: bs58.encode(block.key).toString(),
Size: block.data.length
})
})
}
}

exports.del = {
// uses common parseKey method that returns a `key`
parseArgs: exports.parseKey,

// main route handler which is called after the above `parseArgs`, but only if the args were valid
handler: (request, reply) => {
const key = request.pre.args.key

ipfs.block.del(key, (err, block) => {
if (err) {
log.error(err)
return reply({
Message: 'Failed to get block stats: ' + err,
Code: 0
}).code(500)
}

return reply()
})
}
}

exports.stat = {
// uses common parseKey method that returns a `key`
parseArgs: exports.parseKey,

// main route handler which is called after the above `parseArgs`, but only if the args were valid
handler: (request, reply) => {
const key = request.pre.args.key

ipfs.block.stat(key, (err, block) => {
if (err) {
log.error(err)
return reply({
Message: 'Failed to get block stats: ' + err,
Code: 0
}).code(500)
}

return reply({
Key: bs58.encode(block.Key).toString(),
Size: block.Size
})
})
}
}
Loading