Skip to content

Commit

Permalink
fix: limit concurrent HTTP requests (#12)
Browse files Browse the repository at this point in the history
All HTTP requests made by this module are sent to the same delegate
host. Browsers throttle the number of concurrent requests per hostname,
right now it is 6 per host, which suffocates the use of delegate and
blocking it from being used for preload or delegated content routing.

This introduces a task queue that limits the number of concurrent
requests, making it safe to run in browser context.

See also:
libp2p/js-libp2p-delegated-content-routing#12

License: MIT
Signed-off-by: Marcin Rataj <[email protected]>
  • Loading branch information
lidel authored and jacobheun committed Jul 24, 2019
1 parent f09bf3d commit e844d30
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 6 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,5 @@ docs
.env

yarn.lock
package-lock.json
package-lock.json
dist/
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
"ipfsd-ctl": "^0.44.1"
},
"dependencies": {
"debug": "^4.1.1",
"ipfs-http-client": "^33.1.0",
"p-queue": "^6.1.0",
"peer-id": "~0.12.2"
},
"contributors": [
Expand Down
22 changes: 19 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,31 @@
const PeerId = require('peer-id')
const dht = require('ipfs-http-client/src/dht')
const defaultConfig = require('ipfs-http-client/src/utils/default-config')
const { default: PQueue } = require('p-queue')
const debug = require('debug')

const log = debug('libp2p-delegated-peer-routing')
log.error = debug('libp2p-delegated-peer-routing:error')

const DEFAULT_MAX_TIMEOUT = 30e3 // 30 second default
const DEFAULT_IPFS_API = {
protocol: 'https',
port: 443,
host: 'ipfs.io'
host: 'node0.delegate.ipfs.io'
}
const CONCURRENT_HTTP_REQUESTS = 4

class DelegatedPeerRouting {
constructor (api) {
this.api = Object.assign({}, defaultConfig(), DEFAULT_IPFS_API, api)
this.dht = dht(this.api)

// limit concurrency to avoid request flood in web browser
// https://github.com/libp2p/js-libp2p-delegated-content-routing/issues/12
this._httpQueue = new PQueue({
concurrency: CONCURRENT_HTTP_REQUESTS
})
log(`enabled DelegatedPeerRouting via ${this.api.protocol}://${this.api.host}:${this.api.port}`)
}

/**
Expand All @@ -29,19 +42,22 @@ class DelegatedPeerRouting {
if (PeerId.isPeerId(id)) {
id = id.toB58String()
}
log('findPeer starts: ' + id)

options.maxTimeout = options.maxTimeout || DEFAULT_MAX_TIMEOUT

try {
return await this.dht.findPeer(id, {
return await this._httpQueue.add(() => this.dht.findPeer(id, {
timeout: `${options.maxTimeout}ms`// The api requires specification of the time unit (s/ms)
})
}))
} catch (err) {
if (err.message.includes('not found')) {
return undefined
}

throw err
} finally {
log('findPeer finished: ' + id)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions test/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@ describe('DelegatedPeerRouting', function () {
})

describe('create', () => {
it('should default to https://ipfs.io as the delegate', () => {
it('should default to https://node0.delegate.ipfs.io as the delegate', () => {
const router = new DelegatedPeerRouting()

expect(router.api).to.include({
'api-path': '/api/v0/',
protocol: 'https',
port: 443,
host: 'ipfs.io'
host: 'node0.delegate.ipfs.io'
})
})

Expand Down

0 comments on commit e844d30

Please sign in to comment.