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

feat: allow urls with authentication #28

Merged
merged 7 commits into from
Nov 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 3 additions & 16 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

const root = require('window-or-global')
const IpfsApi = require('ipfs-http-client')
const multiaddr = require('multiaddr')
const tryCompanion = require('./companion')
const tryWindow = require('./window.ipfs')
const tryApi = require('./js-ipfs-api')
const tryJsIpfs = require('./js-ipfs')
const { isURL, isMultiaddress } = require('./utils')

const defaultOptions = {
tryWindow: true,
Expand Down Expand Up @@ -151,7 +151,7 @@ async function getIpfs (opts, { store, getState, dispatch }) {
}
}
if (opts.tryApi) {
const { apiAddress, defaultApiAddress } = getState().ipfs
let { apiAddress, defaultApiAddress } = getState().ipfs
const { location } = root
const res = await tryApi({ apiAddress, defaultApiAddress, location, IpfsApi, ipfsConnectionTest })
if (res) {
Expand All @@ -169,19 +169,6 @@ async function getIpfs (opts, { store, getState, dispatch }) {
dispatch({ type: 'IPFS_INIT_FAILED' })
}

function isMultiaddress (addr) {
if (addr === null || addr === undefined || typeof addr === 'undefined') {
return false
}

try {
multiaddr(addr)
return true
} catch (_) {
return false
}
}

function getUserOpts (key) {
let userOpts = null
if (root.localStorage) {
Expand Down Expand Up @@ -214,7 +201,7 @@ function saveUserOpts (key, val) {

function getUserProvidedIpfsApi () {
const ipfsApi = getUserOpts('ipfsApi')
if (ipfsApi && !isMultiaddress(ipfsApi)) {
if (ipfsApi && !isMultiaddress(ipfsApi) && !isURL(ipfsApi)) {
console.warn(`The ipfsApi address ${ipfsApi} is invalid.`)
return null
}
Expand Down
23 changes: 22 additions & 1 deletion src/js-ipfs-api/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/* eslint-env browser, webextensions */
const toMultiaddr = require('uri-to-multiaddr')
const { isURL } = require('../utils')
const provider = 'js-ipfs-api'

// 1. Try user specified API address
Expand Down Expand Up @@ -41,13 +43,32 @@ async function tryApi ({ IpfsApi, apiAddress, defaultApiAddress, location, ipfsC

// Helper to construct and test an api client. Returns an js-ipfs-api instance or null
async function maybeApi ({ apiAddress, apiOpts, ipfsConnectionTest, IpfsApi }) {
const address = isURL(apiAddress) ? parseURL(apiAddress) : apiAddress

try {
const ipfs = new IpfsApi(apiAddress, apiOpts)
const ipfs = new IpfsApi(address, apiOpts)
await ipfsConnectionTest(ipfs)
return { ipfs, provider, apiAddress }
} catch (error) {
console.log('Failed to connect to ipfs-api', apiAddress)
}
}

function parseURL (addr) {
const url = new URL(addr)

const opts = {
host: url.hostname,
port: url.port,
protocol: url.protocol.slice(0, -1),
headers: {}
}

if (url.username) {
opts.headers.authorization = `Basic ${btoa(unescape(encodeURIComponent(url.username + ':' + url.password)))}`
}

return opts
}

module.exports = tryApi
38 changes: 38 additions & 0 deletions src/js-ipfs-api/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,41 @@ it('Should use the defaultApiAddress if location fails', async (done) => {
expect(config.protocol).toEqual('http')
done()
})

it('Should use the apiAddress (url)', async (done) => {
const opts = {
apiAddress: 'http://1.1.1.1:1111',
defaultApiAddress: '/ip4/127.0.0.1/tcp/5001',
location: new URL('http://localhost:5001'),
IpfsApi: IpfsApi,
ipfsConnectionTest: jest.fn().mockResolvedValueOnce(true)
}
const res = await tryApi(opts)
expect(res.apiAddress).toEqual(opts.apiAddress)
expect(res.provider).toEqual('js-ipfs-api')
expect(opts.ipfsConnectionTest.mock.calls.length).toBe(1)
const config = res.ipfs.getEndpointConfig()
expect(config.host).toEqual('1.1.1.1')
expect(config.port).toEqual('1111')
expect(config.protocol).toEqual('http')
done()
})

it('Should use the apiAddress (url with basic auth)', async (done) => {
const opts = {
apiAddress: 'http://user:pass@1.1.1.1:1111',
defaultApiAddress: '/ip4/127.0.0.1/tcp/5001',
location: new URL('http://localhost:5001'),
IpfsApi: IpfsApi,
ipfsConnectionTest: jest.fn().mockResolvedValueOnce(true)
}
const res = await tryApi(opts)
expect(res.apiAddress).toEqual(opts.apiAddress)
expect(res.provider).toEqual('js-ipfs-api')
expect(opts.ipfsConnectionTest.mock.calls.length).toBe(1)
const config = res.ipfs.getEndpointConfig()
expect(config.host).toEqual('1.1.1.1')
expect(config.port).toEqual('1111')
expect(config.protocol).toEqual('http')
done()
})
32 changes: 32 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict'
/* eslint-env browser, webextensions */

const multiaddr = require('multiaddr')

function isMultiaddress (addr) {
if (addr === null || addr === undefined || typeof addr === 'undefined') {
return false
}

Comment on lines +7 to +10
Copy link
Contributor

Choose a reason for hiding this comment

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

sneaked in during refactoring, can be removed, try/catch below is enough

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is on isMultiaddr and not on isUrl. Our multiaddr does not throw with undefined nor null. I'll leave this check, but the one on isUrl was removed.

try {
multiaddr(addr)
return true
} catch (_) {
return false
}
}

function isURL (addr) {
try {
// eslint-disable-next-line
new URL(addr)
return true
} catch (e) {
return false
}
}

module.exports = {
isMultiaddress,
isURL
}