diff --git a/CHANGELOG.md b/CHANGELOG.md
index 850618174..1ed4603c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,14 @@
+
+## [32.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v32.0.0...v32.0.1) (2019-05-21)
+
+
+### Bug Fixes
+
+* error reporting for non-JSON responses ([#1016](https://github.com/ipfs/js-ipfs-http-client/issues/1016)) ([4251c88](https://github.com/ipfs/js-ipfs-http-client/commit/4251c88)), closes [#912](https://github.com/ipfs/js-ipfs-http-client/issues/912) [#1000](https://github.com/ipfs/js-ipfs-http-client/issues/1000) [#1001](https://github.com/ipfs/js-ipfs-http-client/issues/1001)
+* send trickle param to trigger trickle dag builder ([#1015](https://github.com/ipfs/js-ipfs-http-client/issues/1015)) ([a28b009](https://github.com/ipfs/js-ipfs-http-client/commit/a28b009))
+
+
+
# [32.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v31.1.0...v32.0.0) (2019-05-21)
diff --git a/package.json b/package.json
index 409c0c7ec..50f63ae52 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ipfs-http-client",
- "version": "32.0.0",
+ "version": "32.0.1",
"description": "A client library for the IPFS HTTP API",
"leadMaintainer": "Alan Shaw ",
"main": "src/index.js",
diff --git a/src/utils/send-files-stream.js b/src/utils/send-files-stream.js
index c2450d39e..4c91798fc 100644
--- a/src/utils/send-files-stream.js
+++ b/src/utils/send-files-stream.js
@@ -81,6 +81,10 @@ module.exports = (send, path) => {
qs['wrap-with-directory'] = propOrProp(options, 'wrap-with-directory', 'wrapWithDirectory')
qs.hash = propOrProp(options, 'hash', 'hashAlg')
+ if (options.strategy === 'trickle' || options.trickle) {
+ qs['trickle'] = 'true'
+ }
+
const args = {
path: path,
qs: qs,
diff --git a/src/utils/send-request.js b/src/utils/send-request.js
index 219327adf..1645969f2 100644
--- a/src/utils/send-request.js
+++ b/src/utils/send-request.js
@@ -13,8 +13,26 @@ const log = require('debug')('ipfs-http-client:request')
// -- Internal
+function hasJSONHeaders (res) {
+ return res.headers['content-type'] &&
+ res.headers['content-type'].indexOf('application/json') === 0
+}
+
function parseError (res, cb) {
const error = new Error(`Server responded with ${res.statusCode}`)
+ error.statusCode = res.statusCode
+
+ if (!hasJSONHeaders(res)) {
+ return streamToValue(res, (err, data) => { // eslint-disable-line handle-callback-err
+ // the `err` here refers to errors in stream processing, which
+ // we ignore here, since we already have a valid `error` response
+ // from the server above that we have to report to the caller.
+ if (data && data.length) {
+ error.message = data.toString()
+ }
+ cb(error)
+ })
+ }
streamToJsonValue(res, (err, payload) => {
if (err) {
@@ -34,8 +52,7 @@ function onRes (buffer, cb) {
return (res) => {
const stream = Boolean(res.headers['x-stream-output'])
const chunkedObjects = Boolean(res.headers['x-chunked-output'])
- const isJson = res.headers['content-type'] &&
- res.headers['content-type'].indexOf('application/json') === 0
+ const isJson = hasJSONHeaders(res)
if (res.req) {
log(res.req.method, `${res.req.getHeaders().host}${res.req.path}`, res.statusCode, res.statusMessage)
diff --git a/src/utils/stream-to-json-value.js b/src/utils/stream-to-json-value.js
index e42de2fc6..2ae83e50d 100644
--- a/src/utils/stream-to-json-value.js
+++ b/src/utils/stream-to-json-value.js
@@ -24,7 +24,7 @@ function streamToJsonValue (res, cb) {
try {
res = JSON.parse(data)
} catch (err) {
- return cb(err)
+ return cb(new Error(`Invalid JSON: ${data}`))
}
cb(null, res)
diff --git a/test/request-api.spec.js b/test/request-api.spec.js
index 02f342e53..a9b2fcf2e 100644
--- a/test/request-api.spec.js
+++ b/test/request-api.spec.js
@@ -65,3 +65,77 @@ describe('trailer headers', () => {
})
})
})
+
+describe('error handling', () => {
+ it('should handle plain text error response', function (done) {
+ if (!isNode) return this.skip()
+
+ const server = require('http').createServer((req, res) => {
+ // Consume the entire request, before responding.
+ req.on('data', () => {})
+ req.on('end', () => {
+ // Write a text/plain response with a 403 (forbidden) status
+ res.writeHead(403, { 'Content-Type': 'text/plain' })
+ res.write('ipfs method not allowed')
+ res.end()
+ })
+ })
+
+ server.listen(6001, () => {
+ ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => {
+ expect(err).to.exist()
+ expect(err.statusCode).to.equal(403)
+ expect(err.message).to.equal('ipfs method not allowed')
+ server.close(done)
+ })
+ })
+ })
+
+ it('should handle JSON error response', function (done) {
+ if (!isNode) return this.skip()
+
+ const server = require('http').createServer((req, res) => {
+ // Consume the entire request, before responding.
+ req.on('data', () => {})
+ req.on('end', () => {
+ // Write a application/json response with a 400 (bad request) header
+ res.writeHead(400, { 'Content-Type': 'application/json' })
+ res.write(JSON.stringify({ Message: 'client error', Code: 1 }))
+ res.end()
+ })
+ })
+
+ server.listen(6001, () => {
+ ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => {
+ expect(err).to.exist()
+ expect(err.statusCode).to.equal(400)
+ expect(err.message).to.equal('client error')
+ expect(err.code).to.equal(1)
+ server.close(done)
+ })
+ })
+ })
+
+ it('should handle JSON error response with invalid JSON', function (done) {
+ if (!isNode) return this.skip()
+
+ const server = require('http').createServer((req, res) => {
+ // Consume the entire request, before responding.
+ req.on('data', () => {})
+ req.on('end', () => {
+ // Write a application/json response with a 400 (bad request) header
+ res.writeHead(400, { 'Content-Type': 'application/json' })
+ res.write('{ Message: ')
+ res.end()
+ })
+ })
+
+ server.listen(6001, () => {
+ ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => {
+ expect(err).to.exist()
+ expect(err.message).to.include('Invalid JSON')
+ server.close(done)
+ })
+ })
+ })
+})