Skip to content
This repository has been archived by the owner on Mar 10, 2020. It is now read-only.

Commit

Permalink
fix: Replace http.request with request
Browse files Browse the repository at this point in the history
  • Loading branch information
dignifiedquire committed Nov 2, 2015
1 parent cc9ec51 commit 1588294
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 103 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"parser": "babel-eslint",
"extends": "standard"
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"merge-stream": "^1.0.0",
"multiaddr": "^1.0.0",
"multipart-stream": "^2.0.0",
"request": "^2.65.0",
"vinyl": "^0.5.1",
"vinyl-fs-browser": "^2.1.1-1",
"vinyl-multipart-stream": "^1.2.6"
Expand All @@ -25,7 +26,7 @@
"url": "https://github.com/ipfs/js-ipfs-api"
},
"devDependencies": {
"brfs": "^1.4.1",
"babel-eslint": "^4.1.3",
"browserify": "^11.0.0",
"concurrently": "^0.1.1",
"eslint-config-standard": "^4.4.0",
Expand Down
3 changes: 1 addition & 2 deletions src/get-files-stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ exports = module.exports = getFilesStream

function getFilesStream (files, opts) {
if (!files) return null
if (!Array.isArray(files)) files = [files]

// merge all inputs into one stream
var adder = new Merge()
Expand All @@ -31,7 +30,7 @@ function getFilesStream (files, opts) {
adder.add(vinylfs.src(file, srcOpts))

// if recursive, glob the contents
if (opts.r || opts.recursive) {
if (opts.recursive) {
adder.add(vinylfs.src(file + '/**/*', srcOpts))
}
} else {
Expand Down
199 changes: 107 additions & 92 deletions src/request-api.js
Original file line number Diff line number Diff line change
@@ -1,108 +1,123 @@
var http = require('http')
var qs = require('querystring')
var getFilesStream = require('./get-files-stream')
'use strict'

exports = module.exports = function getRequestAPI (config) {
return requestAPI
const request = require('request')
const getFilesStream = require('./get-files-stream')

function requestAPI (path, args, opts, files, buffer, cb) {
var query, stream, contentType
contentType = 'application/json'
const isNode = !global.window

if (Array.isArray(path)) path = path.join('/')
// -- Internal

opts = opts || {}
function onEnd (buffer, result, cb) {
return (err, res, body) => {
if (err) {
return cb(err)
}

if (args && !Array.isArray(args)) args = [args]
if (args) opts.arg = args
if (res.statusCode >= 400 || !res.statusCode) {
return cb(new Error(`Server responded with ${res.statusCode}: ${body}`))
}

if (files) {
stream = getFilesStream(files, opts)
if (!stream.boundary) {
throw new Error('no boundary in multipart stream')
}
contentType = 'multipart/form-data; boundary=' + stream.boundary
if ((result.stream && !buffer) ||
(result.chunkedObjects && buffer)) {
return cb(null, body)
}

if (typeof buffer === 'function') {
cb = buffer
buffer = false
if (result.chunkedObjects) return cb(null, result.objects)

try {
const parsedBody = JSON.parse(body)
cb(null, parsedBody)
} catch (e) {
cb(null, body)
}
}
}

// this option is only used internally, not passed to daemon
delete opts.followSymlinks

opts['stream-channels'] = true
query = qs.stringify(opts)

var reqo = {
method: files ? 'POST' : 'GET',
host: config.host,
port: config.port,
path: config['api-path'] + path + '?' + query,
headers: {
'User-Agent': config['user-agent'],
'Content-Type': contentType
},
withCredentials: false
function onData (result) {
return chunk => {
if (!result.chunkedObjects) return

try {
const obj = JSON.parse(chunk.toString())
result.objects.push(obj)
} catch (e) {
result.chunkedObjects = false
}
}
}

function onResponse (result) {
return res => {
result.stream = !!res.headers['x-stream-output']
result.chunkedObjects = !!res.headers['x-chunked-output']
}
}

function makeRequest (opts, buffer, cb) {
// this option is only used internally, not passed to daemon
delete opts.qs.followSymlinks

const result = {
stream: false,
chunkedObjects: false,
objects: []
}

return request(opts, onEnd(buffer, result, cb))
.on('data', onData(result))
.on('response', onResponse(result))
}

function requestAPI (config, path, args, qs, files, buffer, cb) {
qs = qs || {}
if (Array.isArray(path)) path = path.join('/')
if (args && !Array.isArray(args)) args = [args]
if (args) qs.arg = args
if (files && !Array.isArray(files)) files = [files]

if (typeof buffer === 'function') {
cb = buffer
buffer = false
}

if (qs.r) qs.recursive = qs.r

if (!isNode && qs.recursive && path === 'add') {
return cb(new Error('Recursive uploads are not supported in the browser'))
}

qs['stream-channels'] = true

var req = http.request(reqo, function (res) {
var data = ''
var objects = []
var stream = !!res.headers && !!res.headers['x-stream-output']
var chunkedObjects = !!res.headers && !!res.headers['x-chunked-output']

if (stream && !buffer) return cb(null, res)
if (chunkedObjects && buffer) return cb(null, res)

res.on('data', function (chunk) {
if (!chunkedObjects) {
data += chunk
return data
}

try {
var obj = JSON.parse(chunk.toString())
objects.push(obj)
} catch (e) {
chunkedObjects = false
data += chunk
}
})
res.on('end', function () {
var parsed

if (!chunkedObjects) {
try {
parsed = JSON.parse(data)
data = parsed
} catch (e) {}
} else {
data = objects
}

if (res.statusCode >= 400 || !res.statusCode) {
if (!data) data = new Error()
return cb(data, null)
}
return cb(null, data)
})
res.on('error', function (err) {
return cb(err, null)
})
})

req.on('error', function (err) {
return cb(err, null)
})

if (stream) {
stream.pipe(req)
} else {
req.end()
const opts = {
method: files ? 'POST' : 'GET',
uri: `http://${config.host}:${config.port}${config['api-path']}${path}`,
qs: qs,
useQuerystring: true,
headers: {},
withCredentials: false,
gzip: true
}

if (isNode) {
// Browsers do not allow you to modify the user agent
opts.headers['User-Agent'] = config['user-agent']
}

if (files) {
const stream = getFilesStream(files, qs)
if (!stream.boundary) {
return cb(new Error('No boundary in multipart stream'))
}

return req
opts.headers['Content-Type'] = `multipart/form-data; boundary=${stream.boundary}`
stream.pipe(makeRequest(opts, buffer, cb))
} else {
makeRequest(opts, buffer, cb)
}
}

// -- Interface

exports = module.exports = function getRequestAPI (config) {
return requestAPI.bind(null, config)
}
17 changes: 9 additions & 8 deletions test/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,18 +130,19 @@ describe('IPFS Node.js API wrapper tests', function () {
})

it('add a nested dir', function (done) {
if (!isNode) {
return done()
}
this.timeout(10000)

apiClients['a'].add(__dirname + '/test-folder', { recursive: true }, function (err, res) {
if (err) {
throw err
if (isNode) {
if (err) throw err

var added = res[res.length - 1]
assert.equal(added.Hash, 'QmZdsefMGMeG6bL719gX44XSVQrL6psEgRZdw1SGadFaK2')
done()
} else {
assert.equal(err.message, 'Recursive uploads are not supported in the browser')
done()
}
var added = res[res.length - 1]
assert.equal(added.Hash, 'QmZdsefMGMeG6bL719gX44XSVQrL6psEgRZdw1SGadFaK2')
done()
})
})
})
Expand Down

0 comments on commit 1588294

Please sign in to comment.