diff --git a/CHANGELOG.md b/CHANGELOG.md index c87f31628..39b1baa1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ + +# [22.1.0](https://github.com/ipfs/js-ipfs-api/compare/v22.0.2...v22.1.0) (2018-06-18) + + +### Features + +* add support for custom headers to send-request ([#741](https://github.com/ipfs/js-ipfs-api/issues/741)) ([7fb2e07](https://github.com/ipfs/js-ipfs-api/commit/7fb2e07)) +* implement bitswap wantlist peer ID param and bitswap unwant ([#761](https://github.com/ipfs/js-ipfs-api/issues/761)) ([73a153e](https://github.com/ipfs/js-ipfs-api/commit/73a153e)) + + + ## [22.0.2](https://github.com/ipfs/js-ipfs-api/compare/v22.0.1...v22.0.2) (2018-06-14) diff --git a/README.md b/README.md index 6bd4cf6ce..4492bb695 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,21 @@ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Credentials "[\"true\"]" ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods "[\"PUT\", \"POST\", \"GET\"]" ``` +### Custom Headers + +If you wish to send custom headers with each request made by this library, for example, the Authorization header. You can use the config to do so: + +``` +const ipfs = IpfsApi({ + host: 'localhost', + port: 5001, + protocol: 'http', + headers: { + authorization: 'Bearer ' + TOKEN + } +}) +``` + ## Usage ### API diff --git a/package.json b/package.json index fda509b7e..aa058a8de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-api", - "version": "22.0.2", + "version": "22.1.0", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", @@ -79,7 +79,7 @@ "eslint-plugin-react": "^7.9.1", "go-ipfs-dep": "~0.4.15", "gulp": "^3.9.1", - "interface-ipfs-core": "~0.67.0", + "interface-ipfs-core": "~0.68.1", "ipfsd-ctl": "~0.37.3", "pull-stream": "^3.6.8", "socket.io": "^2.1.1", @@ -109,6 +109,7 @@ "Fil ", "Francisco Baio Dias ", "Friedel Ziegelmayer ", + "Gar ", "Gavin McDermott ", "Greenkeeper ", "Haad ", @@ -137,6 +138,7 @@ "Mithgol ", "Nuno Nogueira ", "Oli Evans ", + "Orie Steele ", "Pedro Teixeira ", "Pete Thomas ", "Richard Littauer ", diff --git a/src/bitswap/unwant.js b/src/bitswap/unwant.js index 267568ee1..865fbc27b 100644 --- a/src/bitswap/unwant.js +++ b/src/bitswap/unwant.js @@ -1,16 +1,24 @@ 'use strict' const promisify = require('promisify-es6') +const CID = require('cids') module.exports = (send) => { - return promisify((args, opts, callback) => { + return promisify((cid, opts, callback) => { if (typeof (opts) === 'function') { callback = opts opts = {} } + + try { + cid = new CID(cid) + } catch (err) { + return callback(err) + } + send({ path: 'bitswap/unwant', - args: args, + args: cid.toBaseEncodedString(), qs: opts }, callback) }) diff --git a/src/bitswap/wantlist.js b/src/bitswap/wantlist.js index c96aaaaac..6cd1e3868 100644 --- a/src/bitswap/wantlist.js +++ b/src/bitswap/wantlist.js @@ -1,11 +1,30 @@ 'use strict' const promisify = require('promisify-es6') +const CID = require('cids') module.exports = (send) => { - return promisify((callback) => { + return promisify((peerId, opts, callback) => { + if (typeof (peerId) === 'function') { + callback = peerId + opts = {} + peerId = null + } else if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + + if (peerId) { + try { + opts.peer = new CID(peerId).toBaseEncodedString() + } catch (err) { + return callback(err) + } + } + send({ - path: 'bitswap/wantlist' + path: 'bitswap/wantlist', + qs: opts }, callback) }) } diff --git a/src/utils/send-request.js b/src/utils/send-request.js index 90f436d47..eb9ea6adc 100644 --- a/src/utils/send-request.js +++ b/src/utils/send-request.js @@ -106,7 +106,7 @@ function requestAPI (config, options, callback) { delete options.qs.followSymlinks const method = 'POST' - const headers = {} + const headers = Object.assign({}, config.headers) if (isNode) { // Browsers do not allow you to modify the user agent diff --git a/test/bitswap.spec.js b/test/bitswap.spec.js deleted file mode 100644 index 2f7844289..000000000 --- a/test/bitswap.spec.js +++ /dev/null @@ -1,69 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - -const IPFSApi = require('../src') - -const f = require('./utils/factory') - -describe('.bitswap', function () { - this.timeout(20 * 1000) // slow CI - - let ipfs - let ipfsd = null - - before(function (done) { - this.timeout(20 * 1000) // slow CI - - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = IPFSApi(_ipfsd.apiAddr) - done() - }) - }) - - after((done) => { - if (!ipfsd) return done() - ipfsd.stop(done) - }) - - it('.wantlist', (done) => { - ipfs.bitswap.wantlist((err, res) => { - expect(err).to.not.exist() - expect(res).to.have.to.eql({ - Keys: [] - }) - done() - }) - }) - - it('.stat', (done) => { - ipfs.bitswap.stat((err, res) => { - expect(err).to.not.exist() - expect(res).to.have.a.property('provideBufLen') - expect(res).to.have.a.property('wantlist') - expect(res).to.have.a.property('peers') - expect(res).to.have.a.property('blocksReceived') - expect(res).to.have.a.property('dataReceived') - expect(res).to.have.a.property('blocksSent') - expect(res).to.have.a.property('dataSent') - expect(res).to.have.a.property('dupBlksReceived') - expect(res).to.have.a.property('dupDataReceived') - - done() - }) - }) - - it('.unwant', (done) => { - const key = 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP' - ipfs.bitswap.unwant(key, (err) => { - expect(err).to.not.exist() - done() - }) - }) -}) diff --git a/test/custom-headers.spec.js b/test/custom-headers.spec.js new file mode 100644 index 000000000..2cf4c71c3 --- /dev/null +++ b/test/custom-headers.spec.js @@ -0,0 +1,61 @@ +/* eslint-env mocha */ +'use strict' + +const isNode = require('detect-node') +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const expect = chai.expect +chai.use(dirtyChai) + +const IPFSApi = require('../src') +const f = require('./utils/factory') + +describe('custom headers', function () { + // do not test in browser + if (!isNode) { return } + this.timeout(50 * 1000) // slow CI + let ipfs + let ipfsd + // initialize ipfs with custom headers + before(done => { + f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + expect(err).to.not.exist() + ipfsd = _ipfsd + ipfs = IPFSApi({ + host: 'localhost', + port: 6001, + protocol: 'http', + headers: { + authorization: 'Bearer ' + 'YOLO' + } + }) + done() + }) + }) + + it('are supported', done => { + // spin up a test http server to inspect the requests made by the library + const server = require('http').createServer((req, res) => { + req.on('data', () => {}) + req.on('end', () => { + res.writeHead(200) + res.end() + // ensure custom headers are present + expect(req.headers.authorization).to.equal('Bearer ' + 'YOLO') + server.close() + done() + }) + }) + + server.listen(6001, () => { + ipfs.id((err, res) => { + if (err) { + throw new Error('Unexpected error.') + } + // this call is used to test that headers are being sent. + }) + }) + }) + + after(done => ipfsd.stop(done)) +}) diff --git a/test/interface/bitswap.spec.js b/test/interface/bitswap.spec.js new file mode 100644 index 000000000..82eaacb6d --- /dev/null +++ b/test/interface/bitswap.spec.js @@ -0,0 +1,32 @@ +/* eslint-env mocha */ + +'use strict' + +const test = require('interface-ipfs-core') +const parallel = require('async/parallel') + +const IPFSApi = require('../../src') +const f = require('../utils/factory') + +const nodes = [] +const common = { + setup: function (callback) { + callback(null, { + spawnNode: (cb) => { + f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + if (err) { + return cb(err) + } + + nodes.push(_ipfsd) + cb(null, IPFSApi(_ipfsd.apiAddr)) + }) + } + }) + }, + teardown: function (callback) { + parallel(nodes.map((node) => (cb) => node.stop(cb)), callback) + } +} + +test.bitswap(common)