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

Commit

Permalink
feat: browser pubsub (#1059)
Browse files Browse the repository at this point in the history
This PR enabled pubsub in the browser and paves the way for a switch to using `fetch` by default and allowing for cancelable requests via the use of `AbortController`.

It's mostly the work done in ipfs-shipyard/js-ipfs-http-client-lite#1 but adapted a bit for use here.

If approved, we can start work moving the other commands to use `fetch`. The work in https://github.com/ipfs-shipyard/js-ipfs-http-client-lite has proven the hard parts (uploading files) are all possible using the `fetch` API.

Since `fetch` is promise based, when moving the other commands it makes sense to just switch to async/await as per ipfs/js-ipfs#1670 (and callbackify instead of promisify).

Depends on:

* [x] ipfs-inactive/interface-js-ipfs-core#505

resolves #518
refs ipfs/js-ipfs#2093
resolves #932

License: MIT
Signed-off-by: Alan Shaw <alan.shaw@protocol.ai>
  • Loading branch information
Alan Shaw authored Aug 28, 2019
1 parent 07e6841 commit 3764d06
Show file tree
Hide file tree
Showing 22 changed files with 618 additions and 467 deletions.
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"coverage": "npx nyc -r html npm run test:node -- --bail"
},
"dependencies": {
"abort-controller": "^3.0.0",
"async": "^2.6.1",
"bignumber.js": "^9.0.0",
"bl": "^3.0.0",
Expand All @@ -44,6 +45,7 @@
"detect-node": "^2.0.4",
"end-of-stream": "^1.4.1",
"err-code": "^1.1.2",
"explain-error": "^1.0.4",
"flatmap": "0.0.3",
"glob": "^7.1.3",
"ipfs-block": "~0.8.1",
Expand All @@ -56,9 +58,12 @@
"is-stream": "^2.0.0",
"iso-stream-http": "~0.1.2",
"iso-url": "~0.4.6",
"iterable-ndjson": "^1.1.0",
"just-kebab-case": "^1.1.0",
"just-map-keys": "^1.1.0",
"kind-of": "^6.0.2",
"ky": "^0.11.2",
"ky-universal": "^0.2.2",
"lru-cache": "^5.1.1",
"multiaddr": "^6.0.6",
"multibase": "~0.6.0",
Expand All @@ -68,6 +73,7 @@
"once": "^1.4.0",
"peer-id": "~0.12.3",
"peer-info": "~0.15.1",
"promise-nodeify": "^3.0.1",
"promisify-es6": "^1.0.3",
"pull-defer": "~0.2.3",
"pull-stream": "^3.6.9",
Expand All @@ -86,7 +92,7 @@
"cross-env": "^5.2.0",
"dirty-chai": "^2.0.1",
"go-ipfs-dep": "0.4.21",
"interface-ipfs-core": "^0.109.0",
"interface-ipfs-core": "^0.111.0",
"ipfsd-ctl": "~0.43.0",
"nock": "^10.0.2",
"stream-equal": "^1.1.1"
Expand Down
59 changes: 59 additions & 0 deletions src/lib/configure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use strict'
/* eslint-env browser */

const ky = require('ky-universal').default
const { isBrowser, isWebWorker } = require('ipfs-utils/src/env')
const { toUri } = require('./multiaddr')
const errorHandler = require('./error-handler')

// Set default configuration and call create function with them
module.exports = create => config => {
config = config || {}

if (typeof config === 'string') {
config = { apiAddr: config }
} else if (config.constructor && config.constructor.isMultiaddr) {
config = { apiAddr: config }
} else {
config = { ...config }
}

config.apiAddr = (config.apiAddr || getDefaultApiAddr(config)).toString()
config.apiAddr = config.apiAddr.startsWith('/') ? toUri(config.apiAddr) : config.apiAddr
config.apiPath = config.apiPath || config['api-path'] || '/api/v0'

return create({
// TODO configure ky to use config.fetch when this is released:
// https://github.com/sindresorhus/ky/pull/153
ky: ky.extend({
prefixUrl: config.apiAddr + config.apiPath,
timeout: config.timeout || 60 * 1000,
headers: config.headers,
hooks: {
afterResponse: [errorHandler]
}
}),
...config
})
}

function getDefaultApiAddr ({ protocol, host, port }) {
if (isBrowser || isWebWorker) {
if (!protocol && !host && !port) { // Use current origin
return ''
}

if (!protocol) {
protocol = location.protocol.startsWith('http')
? location.protocol.split(':')[0]
: 'http'
}

host = host || location.hostname
port = port || location.port

return `${protocol}://${host}${port ? ':' + port : ''}`
}

return `${protocol || 'http'}://${host || 'localhost'}:${port || 5001}`
}
31 changes: 31 additions & 0 deletions src/lib/error-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict'

const { HTTPError } = require('ky-universal')
const log = require('debug')('ipfs-http-client:lib:error-handler')

function isJsonResponse (res) {
return (res.headers.get('Content-Type') || '').startsWith('application/json')
}

module.exports = async function errorHandler (response) {
if (response.ok) return

let msg

try {
if (isJsonResponse(response)) {
const data = await response.json()
log(data)
msg = data.Message || data.message
} else {
msg = await response.text()
}
} catch (err) {
log('Failed to parse error response', err)
// Failed to extract/parse error message from response
throw new HTTPError(response)
}

if (!msg) throw new HTTPError(response)
throw Object.assign(new Error(msg), { status: response.status })
}
18 changes: 18 additions & 0 deletions src/lib/multiaddr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use strict'

// Convert a multiaddr to a URI
// Assumes multiaddr is in a format that can be converted to a HTTP(s) URI
exports.toUri = ma => {
const parts = `${ma}`.split('/')
const port = getPort(parts)
return `${getProtocol(parts)}://${parts[2]}${port == null ? '' : ':' + port}`
}

function getProtocol (maParts) {
return maParts.indexOf('https') === -1 ? 'http' : 'https'
}

function getPort (maParts) {
const tcpIndex = maParts.indexOf('tcp')
return tcpIndex === -1 ? null : maParts[tcpIndex + 1]
}
25 changes: 25 additions & 0 deletions src/lib/stream-to-iterable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict'

module.exports = function toIterable (body) {
// Node.js stream
if (body[Symbol.asyncIterator]) return body

// Browser ReadableStream
if (body.getReader) {
return (async function * () {
const reader = body.getReader()

try {
while (true) {
const { done, value } = await reader.read()
if (done) return
yield value
}
} finally {
reader.releaseLock()
}
})()
}

throw new Error('unknown stream')
}
212 changes: 0 additions & 212 deletions src/pubsub.js

This file was deleted.

Loading

3 comments on commit 3764d06

@achingbrain
Copy link
Collaborator

@achingbrain achingbrain commented on 3764d06 Sep 16, 2019

Choose a reason for hiding this comment

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

Something in this commit causes this test to time out when run against go-IPFS. Investigation ongoing.

Works with the previous commit, fails with this one.

@alanshaw
Copy link
Contributor

Choose a reason for hiding this comment

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

@achingbrain
Copy link
Collaborator

Choose a reason for hiding this comment

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

That does fix it. Why do we use these bleeding edge libraries?

............................................________
....................................,.-'"...................``~.,
.............................,.-"..................................."-.,
.........................,/...............................................":,
.....................,?......................................................,
.................../...........................................................,}
................./......................................................,:`^`..}
.............../...................................................,:"........./
..............?.....__.........................................:`.........../
............./__.(....."~-,_..............................,:`........../
.........../(_...."~,_........"~,_....................,:`........_/
..........{.._$;_......"=,_......."-,_.......,.-~-,},.~";/....}
...........((.....*~_......."=-._......";,,./`..../"............../
...,,,___.`~,......"~.,....................`.....}............../
............(....`=-,,.......`........................(......;_,,-"
............/.`~,......`-...................................../
.............`~.*-,.....................................|,./.....,__
,,_..........}.>-._...................................|..............`=~-,
.....`=~-,__......`,.................................
...................`=~-,,.,...............................
................................`:,,...........................`..............__
.....................................`=-,...................,%`>--==``
........................................_..........._,-%.......`
...................................,

Please sign in to comment.