diff --git a/README.md b/README.md index 17c5778..6350af9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/tableflip/uri-to-multiaddr.svg?branch=master)](https://travis-ci.org/tableflip/uri-to-multiaddr) [![dependencies Status](https://david-dm.org/tableflip/uri-to-multiaddr/status.svg)](https://david-dm.org/tableflip/uri-to-multiaddr) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) -> Convert a URI to a [Multiaddr](https://multiformats.io/multiaddr/): https://protocol.ai -> /dns4/protocol.ai/https +> Convert a URI to a [Multiaddr](https://multiformats.io/multiaddr/): https://protocol.ai -> /dns4/protocol.ai/tcp/443/https ## Install @@ -16,7 +16,7 @@ npm install uri-to-multiaddr const toMultiaddr = require('uri-to-multiaddr') console.log(toMultiaddr('https://protocol.ai')) -// -> /dns4/protocol.ai/https +// -> /dns4/protocol.ai/tcp/443/https ``` Domain names can represent one of @@ -32,15 +32,15 @@ in an options object as the second parameter to override it: ```js const toMultiaddr = require('uri-to-multiaddr') -console.log(toMultiaddr('https://protocol.ai'), {defaultDnsType: 'dnsaddr'}) -// -> /dnsaddr/protocol.ai/https +console.log(toMultiaddr('https://protocol.ai'), { defaultDnsType: 'dns6' }) +// -> /dns6/protocol.ai/tcp/443/https ``` See [test.js](./test.js) for the currently supported conversions. **Note**: `uri-to-multiaddr` will throw if the passed URI: - is not a valid, according the WHATWG URL spec implementation used. - - is not supported yet e.g. quic + - is not supported yet ## Related diff --git a/index.js b/index.js index 06edb26..dbf1870 100644 --- a/index.js +++ b/index.js @@ -1,13 +1,12 @@ -const url = require('url') const isIp = require('is-ip') const Multiaddr = require('multiaddr') /** * Convert a URI to a multiaddr * - * http://foobar.com => /dns4/foobar.com/https - * https://foobar.com:8080 => /dns4/foobar.com/tcp/8080/https - * ws://foobar.com => /dns4/foobar.com/ws + * http://foobar.com => /dns4/foobar.com/tcp/80/http + * https://foobar.com => /dns4/foobar.com/tcp/443/https + * https://foobar.com:5001 => /dns4/foobar.com/tcp/5001/https * https://127.0.0.1:8080 => /ip4/127.0.0.1/tcp/8080/https * http://[::1]:8080 => /ip6/::1/tcp/8080/http * tcp://foobar.com:8080 => /dns4/foobar.com/tcp/8080 @@ -33,15 +32,16 @@ function multiaddrFromUri (uriStr, opts) { function parseUri (uriStr) { // Use the WHATWG URL global, in node >= 10 and the browser - const { protocol, hostname } = new URL(uriStr) - // WHATWG URL hides port when it's the default for the scheme... - const port = url.parse(uriStr).port + let { protocol, hostname, port } = new URL(uriStr) const scheme = protocol.slice(0, -1) + if (!port && port !== 0) { + port = portForProtocol(scheme) + } return { scheme, hostname, port } } function tupleForHostname (hostname, defaultDnsType) { - if (!hostname) throw new Error('hostname is requried') + if (!hostname) return null if (isIp.v4(hostname)) { return ['ip4', hostname] } @@ -69,10 +69,21 @@ function tupleForPort (port, scheme) { } function tupleForScheme (scheme) { - if (scheme.match(/^https?$|^wss?$/)) { - return [scheme] + if (scheme.match(/^tcp$|^udp$/)) { + return null + } + return [scheme] +} + +function portForProtocol (protocol) { + if (!protocol) return null + const portFor = { + http: '80', + https: '443', + ws: '80', + wss: '443' } - return null + return portFor[protocol] } module.exports = multiaddrFromUri diff --git a/package-lock.json b/package-lock.json index fcd2d5c..f2824a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -882,9 +882,9 @@ } }, "base-x": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.4.tgz", - "integrity": "sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.5.tgz", + "integrity": "sha512-C3picSgzPSLE+jW3tcBzJoGwitOtazb5B+5YmAxZm2ybmTi9LNgAtDO/jjVEBZwHoXmDBZ9m/IELj3elJVRBcA==", "requires": { "safe-buffer": "^5.0.1" } @@ -1110,7 +1110,7 @@ }, "class-is": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==" }, "class-utils": { @@ -2973,27 +2973,6 @@ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" }, - "ip-address": { - "version": "5.8.9", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-5.8.9.tgz", - "integrity": "sha512-7ay355oMN34iXhET1BmCJVsHjOTSItEEIIpOs38qUC23AIhOy+xIPnkrTuEFjeLMrTJ7m8KMXWgWfy/2Vn9sDw==", - "requires": { - "jsbn": "1.1.0", - "lodash.find": "^4.6.0", - "lodash.max": "^4.0.1", - "lodash.merge": "^4.6.0", - "lodash.padstart": "^4.6.1", - "lodash.repeat": "^4.1.0", - "sprintf-js": "1.1.0" - }, - "dependencies": { - "sprintf-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.0.tgz", - "integrity": "sha1-z/yvcC2vZeo5u04PorKZzsGhvkY=" - } - } - }, "ip-regex": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", @@ -3329,11 +3308,6 @@ "esprima": "^4.0.0" } }, - "jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha1-sBMHyym2GKHtJux56RH4A8TaAEA=" - }, "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", @@ -3449,16 +3423,6 @@ "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" }, - "lodash.filter": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", - "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" - }, - "lodash.find": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", - "integrity": "sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E=" - }, "lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", @@ -3474,31 +3438,11 @@ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" }, - "lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" - }, - "lodash.max": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.max/-/lodash.max-4.0.1.tgz", - "integrity": "sha1-hzVWbGGLNan3YFILSHrnllivE2o=" - }, "lodash.merge": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==" }, - "lodash.padstart": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", - "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=" - }, - "lodash.repeat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.repeat/-/lodash.repeat-4.1.0.tgz", - "integrity": "sha1-/H3oEx2MisB+S0n3T/6CnR8r7EQ=" - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -3763,18 +3707,15 @@ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, "multiaddr": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-5.0.0.tgz", - "integrity": "sha512-IMEo+iCv53MT8c/6SQWbJpJUEENTYr6qp7o635BKJLQG2nkxOIO9LSEFhF5e56Az+DkmI6HGAAjp69AT7Sjulw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-6.0.3.tgz", + "integrity": "sha512-ZYKAmSQ6j3x3fJQGF8yoAb5aDwrNFT/QVhfN8rId+M4/E1RYR3fsitFwMG3l7TuWhow+ET01mA+BViz+8NaktQ==", "requires": { "bs58": "^4.0.1", "class-is": "^1.1.0", "ip": "^1.1.5", - "ip-address": "^5.8.9", - "lodash.filter": "^4.6.0", - "lodash.map": "^4.6.0", - "varint": "^5.0.0", - "xtend": "^4.0.1" + "is-ip": "^2.0.0", + "varint": "^5.0.0" } }, "multimatch": { diff --git a/package.json b/package.json index 70ba588..c36531d 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dependencies": { "ava": "^0.25.0", "is-ip": "^2.0.0", - "multiaddr": "^5.0.0" + "multiaddr": "^6.0.3" }, "devDependencies": { "standard": "^12.0.1" diff --git a/test.js b/test.js index a5e0241..ea4619c 100644 --- a/test.js +++ b/test.js @@ -3,8 +3,8 @@ const toMultiaddr = require('./') test('should convert URIs to multiaddrs', (t) => { const data = [ - ['/ip4/127.0.0.1/http', 'http://127.0.0.1'], - ['/ip6/fc00::/http', 'http://[fc00::]'], + ['/ip4/127.0.0.1/tcp/80/http', 'http://127.0.0.1'], + ['/ip6/fc00::/tcp/80/http', 'http://[fc00::]'], ['/ip4/0.0.7.6/tcp/1234', 'tcp://0.0.7.6:1234'], ['/ip4/0.0.7.6/tcp/1234/http', 'http://0.0.7.6:1234'], ['/ip4/0.0.7.6/tcp/1234/https', 'https://0.0.7.6:1234'], @@ -14,17 +14,22 @@ test('should convert URIs to multiaddrs', (t) => { ['/dns4/protocol.ai/tcp/80', 'tcp://protocol.ai:80'], ['/dns4/protocol.ai/tcp/80/http', 'http://protocol.ai:80'], ['/dns4/protocol.ai/tcp/80/https', 'https://protocol.ai:80'], - ['/dns4/ipfs.io/ws', 'ws://ipfs.io'], - ['/dns4/ipfs.io/http', 'http://ipfs.io'], - ['/dns4/ipfs.io/https', 'https://ipfs.io'], + ['/dns4/ipfs.io/tcp/80/ws', 'ws://ipfs.io'], + ['/dns4/ipfs.io/tcp/443/wss', 'wss://ipfs.io'], + ['/dns4/ipfs.io/tcp/80/http', 'http://ipfs.io'], + ['/dns4/ipfs.io/tcp/443/https', 'https://ipfs.io'], ['/ip4/1.2.3.4/tcp/3456/ws', 'ws://1.2.3.4:3456'], + ['/ip4/1.2.3.4/tcp/3456/wss', 'wss://1.2.3.4:3456'], ['/ip6/::/tcp/0/ws', 'ws://[::]:0'], - ['/dns4/ipfs.io/wss', 'wss://ipfs.io'], ['/ip4/1.2.3.4/tcp/3456/wss', 'wss://1.2.3.4:3456'], ['/ip6/::/tcp/0/wss', 'wss://[::]:0'] ] - - data.forEach(d => t.is(toMultiaddr(d[1]).toString(), d[0], `Converts ${d[1]} to ${d[0]}`)) + data.forEach(d => { + const input = d[1] + const expected = d[0] + const output = toMultiaddr(input).toString() + t.is(output, expected, `Converts ${input} to ${expected}`) + }) }) test('should use the defaultDnsType where provided', (t) => { @@ -37,6 +42,15 @@ test('should use the defaultDnsType where provided', (t) => { data.forEach(d => t.is(toMultiaddr(d[1], d[2]).toString(), d[0], `Converts ${d[1]} to ${d[0]} with opts ${d[2]}`)) }) -test('should throw for unsupported protocol', (t) => { - t.throws(() => toMultiaddr('quic://')) +test('should throw for on invalid url', (t) => { + t.throws(() => { + toMultiaddr('whoosh.fast') + }, /Invalid URL/) +}) + +test('should throw for unknown protocol', (t) => { + t.throws(() => { + // NOTE: `data` is a valid uri protocol but isn't a valid multiaddr protocol yet + toMultiaddr('data:image/svg+xml;base64,test') + }, 'no protocol with name: data') })