-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Upgrade the files branch (#323) to work with pull-streams #469
Changes from all commits
76959ac
2bf49ea
e29f429
11cb4ca
001a6eb
cb10ab7
b0a6db9
4050195
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -155,7 +155,6 @@ module.exports = function object (self) { | |
if (err) { | ||
return cb(err) | ||
} | ||
|
||
cb(null, node.data) | ||
}) | ||
}), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,16 @@ | ||
'use strict' | ||
|
||
const bs58 = require('bs58') | ||
const multipart = require('ipfs-multipart') | ||
const debug = require('debug') | ||
const tar = require('tar-stream') | ||
const log = debug('http-api:files') | ||
log.error = debug('http-api:files:error') | ||
const pull = require('pull-stream') | ||
const toStream = require('pull-stream-to-stream') | ||
const toPull = require('stream-to-pull-stream') | ||
const pushable = require('pull-pushable') | ||
const EOL = require('os').EOL | ||
|
||
exports = module.exports | ||
|
||
|
@@ -33,18 +40,152 @@ exports.cat = { | |
// 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 | ||
const ipfs = request.server.app.ipfs | ||
|
||
request.server.app.ipfs.files.cat(key, (err, stream) => { | ||
ipfs.files.cat(key, (err, stream) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
if (err) { | ||
log.error(err) | ||
return reply({ | ||
Message: 'Failed to cat file: ' + err, | ||
Code: 0 | ||
}).code(500) | ||
} | ||
stream.on('data', (data) => { | ||
return reply(data) | ||
|
||
// hapi is not very clever and throws if no | ||
// - _read method | ||
// - _readableState object | ||
// are there :( | ||
stream._read = () => {} | ||
stream._readableState = {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like a bug in Hapi //cc @sericaia |
||
return reply(stream).header('X-Stream-Output', '1') | ||
}) | ||
} | ||
} | ||
|
||
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 | ||
const ipfs = request.server.app.ipfs | ||
const pack = tar.pack() | ||
|
||
ipfs.files.getPull(key, (err, stream) => { | ||
if (err) { | ||
log.error(err) | ||
|
||
reply({ | ||
Message: 'Failed to get file: ' + err, | ||
Code: 0 | ||
}).code(500) | ||
return | ||
} | ||
|
||
pull( | ||
stream, | ||
pull.asyncMap((file, cb) => { | ||
const header = {name: file.path} | ||
|
||
if (!file.content) { | ||
header.type = 'directory' | ||
pack.entry(header) | ||
cb() | ||
} else { | ||
header.size = file.size | ||
toStream.source(file.content) | ||
.pipe(pack.entry(header, cb)) | ||
} | ||
}), | ||
pull.onEnd((err) => { | ||
if (err) { | ||
log.error(err) | ||
|
||
reply({ | ||
Message: 'Failed to get file: ' + err, | ||
Code: 0 | ||
}).code(500) | ||
return | ||
} | ||
|
||
pack.finalize() | ||
}) | ||
) | ||
|
||
// the reply must read the tar stream, | ||
// to pull values through | ||
reply(pack).header('X-Stream-Output', '1') | ||
}) | ||
} | ||
} | ||
|
||
exports.add = { | ||
handler: (request, reply) => { | ||
if (!request.payload) { | ||
return reply('Array, Buffer, or String is required.').code(400).takeover() | ||
} | ||
|
||
const ipfs = request.server.app.ipfs | ||
// TODO: make pull-multipart | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Track this in a issue. @xicombd you probably would like to get that working, since you did the first multipart parser :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
const parser = multipart.reqParser(request.payload) | ||
let filesParsed = false | ||
|
||
const fileAdder = pushable() | ||
|
||
parser.on('file', (fileName, fileStream) => { | ||
const filePair = { | ||
path: fileName, | ||
content: toPull(fileStream) | ||
} | ||
filesParsed = true | ||
fileAdder.push(filePair) | ||
}) | ||
|
||
parser.on('directory', (directory) => { | ||
fileAdder.push({ | ||
path: directory, | ||
content: '' | ||
}) | ||
}) | ||
|
||
parser.on('end', () => { | ||
if (!filesParsed) { | ||
return reply("File argument 'data' is required.") | ||
.code(400).takeover() | ||
} | ||
fileAdder.end() | ||
}) | ||
|
||
pull( | ||
fileAdder, | ||
ipfs.files.createAddPullStream(), | ||
pull.map((file) => { | ||
return { | ||
Name: file.path ? file.path : file.hash, | ||
Hash: file.hash | ||
} | ||
}), | ||
pull.map((file) => JSON.stringify(file) + EOL), | ||
pull.collect((err, files) => { | ||
if (err) { | ||
return reply({ | ||
Message: err, | ||
Code: 0 | ||
}).code(500) | ||
} | ||
|
||
if (files.length === 0 && filesParsed) { | ||
return reply({ | ||
Message: 'Failed to add files.', | ||
Code: 0 | ||
}).code(500) | ||
} | ||
|
||
reply(files.join('')) | ||
.header('x-chunked-output', '1') | ||
.header('content-type', 'application/json') | ||
}) | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ module.exports = (server) => { | |
const api = server.select('API') | ||
|
||
api.route({ | ||
// TODO fix method | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an http-api-spec thing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure who put that there, @victorbjelkholm did you? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I put it there. Mainly as a reminder that we should talk about setting the method of the endpoints in |
||
method: '*', | ||
path: '/api/v0/cat', | ||
config: { | ||
|
@@ -15,4 +16,29 @@ module.exports = (server) => { | |
handler: resources.files.cat.handler | ||
} | ||
}) | ||
|
||
api.route({ | ||
// TODO fix method | ||
method: '*', | ||
path: '/api/v0/get', | ||
config: { | ||
pre: [ | ||
{ method: resources.files.get.parseArgs, assign: 'args' } | ||
], | ||
handler: resources.files.get.handler | ||
} | ||
}) | ||
|
||
api.route({ | ||
// TODO fix method | ||
method: '*', | ||
path: '/api/v0/add', | ||
config: { | ||
payload: { | ||
parse: false, | ||
output: 'stream' | ||
}, | ||
handler: resources.files.add.handler | ||
} | ||
}) | ||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to
pause
the stream? Would it otherwise start emitting without listeners?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what pause?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check the lines above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, data can be lost if I don't pause it, oh my love for node streams is so great
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's weird to me that it starts flowing before a read on a 'data' event is attached.