Skip to content
This repository has been archived by the owner on Feb 12, 2024. 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 #1670 (and callbackify instead of promisify).

Depends on:

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

resolves ipfs-inactive/js-ipfs-http-client#518
refs #2093
resolves ipfs-inactive/js-ipfs-http-client#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

0 comments on commit 3764d06

Please sign in to comment.