From 39a1d610224fe196b1d8b3227397b751d13ca1e8 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Thu, 20 Feb 2025 16:47:10 +0100 Subject: [PATCH 01/19] add poc --- lib/multiaddr.js | 78 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 17 deletions(-) diff --git a/lib/multiaddr.js b/lib/multiaddr.js index b38d9a4..eeebbb4 100644 --- a/lib/multiaddr.js +++ b/lib/multiaddr.js @@ -1,32 +1,76 @@ +import { multiaddr } from '@multiformats/multiaddr' + /** * @param {string} addr Multiaddr, e.g. `/ip4/127.0.0.1/tcp/80/http` * @returns {string} Parsed URI, e.g. `http://127.0.0.1:80` */ export function multiaddrToHttpUrl (addr) { - const [, hostType, hostValue, ipProtocol, port, scheme, ...rest] = addr.split('/') - - if (ipProtocol !== 'tcp') { + const multiaddress = multiaddr(addr) + const parts = multiaddress.stringTuples() + let httpProtocol = null + let ipProtocol = null + let host = null + let port = null + let path = '' + for (const [code, value] of parts) { + switch (code) { + case 4: // IPv4 + case 41: // IPv6 + case 53: // DNS + case 54: // DNS4 + case 55: // DNS6 + case 56: // DNSaddr + ipProtocol = deriveIpProtocol(code) + host = value + break + case 6: // TCP + port = value + break + case 480: // HTTP + case 443: // HTTPS + httpProtocol = deriveHttpProtocol(code) + break + case 481: // HTTP-Path + path = decodeURIComponent(value) + break + } + } + if (!ipProtocol || !host || !httpProtocol) { throw Object.assign( - new Error(`Cannot parse "${addr}": unsupported protocol "${ipProtocol}"`), - { code: 'UNSUPPORTED_MULTIADDR_PROTO' } - ) + new Error(`Cannot parse "${addr}": missing ipProtocol or host or httpProtocol`), + { code: 'MULTIADDR_MISSING_PROTOCOL_OR_HOST' }) } + const hostString = getUriHost(ipProtocol, host) + const portString = getUriPort(httpProtocol, port) + return `${httpProtocol}://${hostString}${portString}${path}` +} - if (scheme !== 'http' && scheme !== 'https') { - throw Object.assign( - new Error(`Cannot parse "${addr}": unsupported scheme "${scheme}"`), - { code: 'UNSUPPORTED_MULTIADDR_SCHEME' } - ) +function deriveIpProtocol (code) { + switch (code) { + case 4: return 'ip4' + case 41: return 'ip6' + case 53: return 'dns' + case 54: return 'dns4' + case 55: return 'dns6' + case 56: return 'dnsaddr' } - if (rest.length) { - throw Object.assign( - new Error(`Cannot parse "${addr}": too many parts`), - { code: 'MULTIADDR_HAS_TOO_MANY_PARTS' } - ) + throw Object.assign( + new Error(`Unsupported multiaddr protocol code "${code}"`), + { code: 'UNSUPPORTED_MULTIADDR_PROTOCOL_CODE' } + ) +} + +function deriveHttpProtocol (code) { + switch (code) { + case 480: return 'http' + case 443: return 'https' } - return `${scheme}://${getUriHost(hostType, hostValue)}${getUriPort(scheme, port)}` + throw Object.assign( + new Error(`Unsupported multiaddr protocol code "${code}"`), + { code: 'UNSUPPORTED_MULTIADDR_PROTOCOL_CODE' } + ) } function getUriHost (hostType, hostValue) { From 8199b2e5676749b38ff95efc073440af080c712c Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Fri, 21 Feb 2025 08:12:43 +0100 Subject: [PATCH 02/19] support http-path --- lib/multiaddr.js | 102 +++++++++++++++++------------------------ test/multiaddr.test.js | 3 +- 2 files changed, 43 insertions(+), 62 deletions(-) diff --git a/lib/multiaddr.js b/lib/multiaddr.js index eeebbb4..13471a0 100644 --- a/lib/multiaddr.js +++ b/lib/multiaddr.js @@ -1,76 +1,56 @@ -import { multiaddr } from '@multiformats/multiaddr' - /** * @param {string} addr Multiaddr, e.g. `/ip4/127.0.0.1/tcp/80/http` * @returns {string} Parsed URI, e.g. `http://127.0.0.1:80` */ export function multiaddrToHttpUrl (addr) { - const multiaddress = multiaddr(addr) - const parts = multiaddress.stringTuples() - let httpProtocol = null - let ipProtocol = null - let host = null - let port = null - let path = '' - for (const [code, value] of parts) { - switch (code) { - case 4: // IPv4 - case 41: // IPv6 - case 53: // DNS - case 54: // DNS4 - case 55: // DNS6 - case 56: // DNSaddr - ipProtocol = deriveIpProtocol(code) - host = value - break - case 6: // TCP - port = value - break - case 480: // HTTP - case 443: // HTTPS - httpProtocol = deriveHttpProtocol(code) - break - case 481: // HTTP-Path - path = decodeURIComponent(value) - break + const [multiAddr, httpPathMultiAddr] = addr.split('/http-path/') + const [, hostType, hostValue, ...multiAddrParts] = multiAddr.split('/') + let scheme, path, rest + if (httpPathMultiAddr) { + scheme = multiAddrParts.shift() + rest = multiAddrParts + path = decodeURIComponent(httpPathMultiAddr) + if (!path) { + throw Object.assign( + new Error(`Cannot parse "${addr}": http-path is empty`), + { code: 'MULTIADDR_HAS_EMPTY_HTTP_PATH' } + ) + } + } else { + const ipProtocol = multiAddrParts.shift() + const port = multiAddrParts.shift() + scheme = multiAddrParts.shift() + rest = multiAddrParts + + if (ipProtocol !== 'tcp') { + throw Object.assign( + new Error(`Cannot parse "${addr}": unsupported protocol "${ipProtocol}"`), + { code: 'UNSUPPORTED_MULTIADDR_PROTO' } + ) } + path = getUriPort(scheme, port) } - if (!ipProtocol || !host || !httpProtocol) { + + if (scheme !== 'http' && scheme !== 'https') { throw Object.assign( - new Error(`Cannot parse "${addr}": missing ipProtocol or host or httpProtocol`), - { code: 'MULTIADDR_MISSING_PROTOCOL_OR_HOST' }) + new Error(`Cannot parse "${addr}": unsupported scheme "${scheme}"`), + { code: 'UNSUPPORTED_MULTIADDR_SCHEME' } + ) } - const hostString = getUriHost(ipProtocol, host) - const portString = getUriPort(httpProtocol, port) - return `${httpProtocol}://${hostString}${portString}${path}` -} -function deriveIpProtocol (code) { - switch (code) { - case 4: return 'ip4' - case 41: return 'ip6' - case 53: return 'dns' - case 54: return 'dns4' - case 55: return 'dns6' - case 56: return 'dnsaddr' + if (rest.length) { + throw Object.assign( + new Error(`Cannot parse "${addr}": too many parts`), + { code: 'MULTIADDR_HAS_TOO_MANY_PARTS' } + ) } - - throw Object.assign( - new Error(`Unsupported multiaddr protocol code "${code}"`), - { code: 'UNSUPPORTED_MULTIADDR_PROTOCOL_CODE' } - ) -} - -function deriveHttpProtocol (code) { - switch (code) { - case 480: return 'http' - case 443: return 'https' + if (scheme !== 'http' && scheme !== 'https') { + throw Object.assign( + new Error(`Cannot parse "${addr}": unsupported scheme "${scheme}"`), + { code: 'UNSUPPORTED_MULTIADDR_SCHEME' } + ) } - - throw Object.assign( - new Error(`Unsupported multiaddr protocol code "${code}"`), - { code: 'UNSUPPORTED_MULTIADDR_PROTOCOL_CODE' } - ) + return `${scheme}://${getUriHost(hostType, hostValue)}${path}` } function getUriHost (hostType, hostValue) { diff --git a/test/multiaddr.test.js b/test/multiaddr.test.js index 4a167ac..95f843a 100644 --- a/test/multiaddr.test.js +++ b/test/multiaddr.test.js @@ -9,7 +9,8 @@ const HAPPY_CASES = [ ['/ip4/127.0.0.1/tcp/8080/https', 'https://127.0.0.1:8080'], ['/dns/meridian.space/tcp/8080/http', 'http://meridian.space:8080'], ['/dns4/meridian.space/tcp/8080/http', 'http://meridian.space:8080'], - ['/dns6/meridian.space/tcp/8080/http', 'http://meridian.space:8080'] + ['/dns6/meridian.space/tcp/8080/http', 'http://meridian.space:8080'], + ['/dns/meridian.space/https/http-path/%2Fipni-provider%2F12D3KooWJ91c8xqshrNe7QAXPFAaeRr0Wq2UrgXGPf8UmMZMwyZ5', 'https://meridian.space/ipni-provider/12D3KooWJ91c8xqshrNe7QAXPFAaeRr0Wq2UrgXGPf8UmMZMwyZ5'] ] for (const [multiaddr, expectedUri] of HAPPY_CASES) { From d1546d77561b014b1331ac3dd1bccbd60f0a519c Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Fri, 21 Feb 2025 10:18:27 +0100 Subject: [PATCH 03/19] add tests for http-path --- lib/multiaddr.js | 34 +++++++++++++++++----------------- lib/spark.js | 2 ++ test/multiaddr.test.js | 7 +++++-- test/spark.js | 14 ++++++++++++++ 4 files changed, 38 insertions(+), 19 deletions(-) diff --git a/lib/multiaddr.js b/lib/multiaddr.js index 13471a0..cdde627 100644 --- a/lib/multiaddr.js +++ b/lib/multiaddr.js @@ -3,22 +3,25 @@ * @returns {string} Parsed URI, e.g. `http://127.0.0.1:80` */ export function multiaddrToHttpUrl (addr) { - const [multiAddr, httpPathMultiAddr] = addr.split('/http-path/') + const [multiAddr, httpPathMultiAddr] = addr.split('/http-path') const [, hostType, hostValue, ...multiAddrParts] = multiAddr.split('/') - let scheme, path, rest - if (httpPathMultiAddr) { + let scheme, path, rest, port + if (addr.includes('/http-path')) { scheme = multiAddrParts.shift() rest = multiAddrParts - path = decodeURIComponent(httpPathMultiAddr) - if (!path) { + try { + // Remove leading slash and parse URI-encoded path + // If the http-path is empty both `.../http-path/` and `.../http-path` are valid + path = decodeURIComponent(httpPathMultiAddr.replace(/^\/+/, '')) + } catch (err) { throw Object.assign( - new Error(`Cannot parse "${addr}": http-path is empty`), - { code: 'MULTIADDR_HAS_EMPTY_HTTP_PATH' } + new Error(`Cannot parse "${addr}": unsupported http path`, { cause: err }), + { code: 'UNSUPPORTED_HTTP_PATH' } ) } } else { const ipProtocol = multiAddrParts.shift() - const port = multiAddrParts.shift() + port = multiAddrParts.shift() scheme = multiAddrParts.shift() rest = multiAddrParts @@ -28,14 +31,6 @@ export function multiaddrToHttpUrl (addr) { { code: 'UNSUPPORTED_MULTIADDR_PROTO' } ) } - path = getUriPort(scheme, port) - } - - if (scheme !== 'http' && scheme !== 'https') { - throw Object.assign( - new Error(`Cannot parse "${addr}": unsupported scheme "${scheme}"`), - { code: 'UNSUPPORTED_MULTIADDR_SCHEME' } - ) } if (rest.length) { @@ -44,13 +39,18 @@ export function multiaddrToHttpUrl (addr) { { code: 'MULTIADDR_HAS_TOO_MANY_PARTS' } ) } + if (scheme !== 'http' && scheme !== 'https') { throw Object.assign( new Error(`Cannot parse "${addr}": unsupported scheme "${scheme}"`), { code: 'UNSUPPORTED_MULTIADDR_SCHEME' } ) } - return `${scheme}://${getUriHost(hostType, hostValue)}${path}` + + let url = `${scheme}://${getUriHost(hostType, hostValue)}` + if (port) url += getUriPort(scheme, port) + if (path) url += path + return url } function getUriHost (hostType, hostValue) { diff --git a/lib/spark.js b/lib/spark.js index 394dcdf..875248a 100644 --- a/lib/spark.js +++ b/lib/spark.js @@ -318,6 +318,8 @@ function mapErrorToStatusCode (err) { return 703 case 'MULTIADDR_HAS_TOO_MANY_PARTS': return 704 + case 'UNSUPPORTED_HTTP_PATH': + return 705 } // 9xx for content verification errors diff --git a/test/multiaddr.test.js b/test/multiaddr.test.js index 95f843a..e2ae25d 100644 --- a/test/multiaddr.test.js +++ b/test/multiaddr.test.js @@ -10,7 +10,8 @@ const HAPPY_CASES = [ ['/dns/meridian.space/tcp/8080/http', 'http://meridian.space:8080'], ['/dns4/meridian.space/tcp/8080/http', 'http://meridian.space:8080'], ['/dns6/meridian.space/tcp/8080/http', 'http://meridian.space:8080'], - ['/dns/meridian.space/https/http-path/%2Fipni-provider%2F12D3KooWJ91c8xqshrNe7QAXPFAaeRr0Wq2UrgXGPf8UmMZMwyZ5', 'https://meridian.space/ipni-provider/12D3KooWJ91c8xqshrNe7QAXPFAaeRr0Wq2UrgXGPf8UmMZMwyZ5'] + ['/dns/meridian.space/https/http-path/%2Fipni-provider%2FproviderID', 'https://meridian.space/ipni-provider/providerID'], + ['/dns/meridian.space/https/http-path/', 'https://meridian.space'] ] for (const [multiaddr, expectedUri] of HAPPY_CASES) { @@ -23,7 +24,9 @@ for (const [multiaddr, expectedUri] of HAPPY_CASES) { const ERROR_CASES = [ ['/ip4/127.0.0.1/tcp/80', 'Cannot parse "/ip4/127.0.0.1/tcp/80": unsupported scheme "undefined"'], ['/ip4/127.0.0.1/udp/90', 'Cannot parse "/ip4/127.0.0.1/udp/90": unsupported protocol "udp"'], - ['/ip4/127.0.0.1/tcp/8080/http/p2p/pubkey', 'Cannot parse "/ip4/127.0.0.1/tcp/8080/http/p2p/pubkey": too many parts'] + ['/ip4/127.0.0.1/tcp/8080/http/p2p/pubkey', 'Cannot parse "/ip4/127.0.0.1/tcp/8080/http/p2p/pubkey": too many parts'], + ['/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID', 'Cannot parse "/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID": too many parts'], + ['/dns/meridian.space/http/http-path/invalid%path', 'Cannot parse "/dns/meridian.space/http/http-path/invalid%path": unsupported http path'] ] for (const [multiaddr, expectedError] of ERROR_CASES) { diff --git a/test/spark.js b/test/spark.js index 53ff3b0..f48f523 100644 --- a/test/spark.js +++ b/test/spark.js @@ -194,6 +194,20 @@ test('fetchCAR fails with statusCode=802 (TCP connection refused)', async () => assertEquals(stats.statusCode, 802, 'stats.statusCode') }) +test('fetchCAR fails with statusCode=704 (multiaddr has too many parts)', async () => { + const spark = new Spark() + const stats = newStats() + await spark.fetchCAR('http', '/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID', KNOWN_CID, stats) + assertEquals(stats.statusCode, 704, 'stats.statusCode') +}) + +test('fetchCAR fails with statusCode=705 (multiaddr has unsupported http-path)', async () => { + const spark = new Spark() + const stats = newStats() + await spark.fetchCAR('http', '/dns/meridian.space/http/http-path/invalid%path', KNOWN_CID, stats) + assertEquals(stats.statusCode, 705, 'stats.statusCode') +}) + // TODO: // statusCode=901 - unsupported hash algorithm From 0e61103529b8a86991d8a96b8b6dad1e04700621 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Fri, 21 Feb 2025 10:33:24 +0100 Subject: [PATCH 04/19] add test for empty http-path --- test/multiaddr.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/multiaddr.test.js b/test/multiaddr.test.js index e2ae25d..40ff0b0 100644 --- a/test/multiaddr.test.js +++ b/test/multiaddr.test.js @@ -11,7 +11,8 @@ const HAPPY_CASES = [ ['/dns4/meridian.space/tcp/8080/http', 'http://meridian.space:8080'], ['/dns6/meridian.space/tcp/8080/http', 'http://meridian.space:8080'], ['/dns/meridian.space/https/http-path/%2Fipni-provider%2FproviderID', 'https://meridian.space/ipni-provider/providerID'], - ['/dns/meridian.space/https/http-path/', 'https://meridian.space'] + ['/dns/meridian.space/https/http-path/', 'https://meridian.space'], + ['/dns/meridian.space/https/http-path', 'https://meridian.space'] ] for (const [multiaddr, expectedUri] of HAPPY_CASES) { From 7f9509021a8c13586c0b7982e306308174faa764 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl <113891786+NikolasHaimerl@users.noreply.github.com> Date: Fri, 21 Feb 2025 17:38:32 +0100 Subject: [PATCH 05/19] Update test/multiaddr.test.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Miroslav Bajtoš --- test/multiaddr.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/multiaddr.test.js b/test/multiaddr.test.js index 40ff0b0..808df57 100644 --- a/test/multiaddr.test.js +++ b/test/multiaddr.test.js @@ -26,6 +26,7 @@ const ERROR_CASES = [ ['/ip4/127.0.0.1/tcp/80', 'Cannot parse "/ip4/127.0.0.1/tcp/80": unsupported scheme "undefined"'], ['/ip4/127.0.0.1/udp/90', 'Cannot parse "/ip4/127.0.0.1/udp/90": unsupported protocol "udp"'], ['/ip4/127.0.0.1/tcp/8080/http/p2p/pubkey', 'Cannot parse "/ip4/127.0.0.1/tcp/8080/http/p2p/pubkey": too many parts'], + // NOTE: This is a valid multiaddr value that we decided to not support yet. ['/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID', 'Cannot parse "/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID": too many parts'], ['/dns/meridian.space/http/http-path/invalid%path', 'Cannot parse "/dns/meridian.space/http/http-path/invalid%path": unsupported http path'] ] From d2c6c6056305204ac6c59ee2fbda1745f5b0315e Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Sun, 23 Feb 2025 15:19:32 +0100 Subject: [PATCH 06/19] chore: fix test formatting --- lib/multiaddr.js | 16 ++++++++-------- lib/spark.js | 2 +- test/spark.js | 31 +++++++++++++++---------------- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/lib/multiaddr.js b/lib/multiaddr.js index cdde627..c586b62 100644 --- a/lib/multiaddr.js +++ b/lib/multiaddr.js @@ -11,12 +11,12 @@ export function multiaddrToHttpUrl (addr) { rest = multiAddrParts try { // Remove leading slash and parse URI-encoded path - // If the http-path is empty both `.../http-path/` and `.../http-path` are valid + // If the http-path is empty both `.../http-path/` and `.../http-path` are valid, see https://github.com/multiformats/multiaddr/blob/cab92e8e6da2e70c5f1b8aa59976e71e6922b392/protocols/http-path.md#usage path = decodeURIComponent(httpPathMultiAddr.replace(/^\/+/, '')) } catch (err) { throw Object.assign( new Error(`Cannot parse "${addr}": unsupported http path`, { cause: err }), - { code: 'UNSUPPORTED_HTTP_PATH' } + { code: 'INVALID_HTTP_PATH' } ) } } else { @@ -33,17 +33,17 @@ export function multiaddrToHttpUrl (addr) { } } - if (rest.length) { + if (scheme !== 'http' && scheme !== 'https') { throw Object.assign( - new Error(`Cannot parse "${addr}": too many parts`), - { code: 'MULTIADDR_HAS_TOO_MANY_PARTS' } + new Error(`Cannot parse "${addr}": unsupported scheme "${scheme}"`), + { code: 'UNSUPPORTED_MULTIADDR_SCHEME' } ) } - if (scheme !== 'http' && scheme !== 'https') { + if (rest.length) { throw Object.assign( - new Error(`Cannot parse "${addr}": unsupported scheme "${scheme}"`), - { code: 'UNSUPPORTED_MULTIADDR_SCHEME' } + new Error(`Cannot parse "${addr}": too many parts`), + { code: 'MULTIADDR_HAS_TOO_MANY_PARTS' } ) } diff --git a/lib/spark.js b/lib/spark.js index 875248a..97228e0 100644 --- a/lib/spark.js +++ b/lib/spark.js @@ -318,7 +318,7 @@ function mapErrorToStatusCode (err) { return 703 case 'MULTIADDR_HAS_TOO_MANY_PARTS': return 704 - case 'UNSUPPORTED_HTTP_PATH': + case 'INVALID_HTTP_PATH': return 705 } diff --git a/test/spark.js b/test/spark.js index f48f523..4e596fa 100644 --- a/test/spark.js +++ b/test/spark.js @@ -165,14 +165,27 @@ test('fetchCAR fails with statusCode=703 (scheme is not http/https)', async () = await spark.fetchCAR('http', '/ip4/1.2.3.4/tcp/80/ldap', KNOWN_CID, stats) assertEquals(stats.statusCode, 703, 'stats.statusCode') }) - -test('fetchCAR fails with statusCode=704 (multiaddr has too many parts)', async () => { +test('fetchCAR fails with statusCode=704 (multiaddr has too many parts) - multiaddr without http-path', async () => { const spark = new Spark() const stats = newStats() await spark.fetchCAR('http', '/ip4/1.2.3.4/tcp/80/http/p2p/pubkey', KNOWN_CID, stats) assertEquals(stats.statusCode, 704, 'stats.statusCode') }) +test('fetchCAR fails with statusCode=704 (multiaddr has too many parts) - multiaddr with http-path', async () => { + const spark = new Spark() + const stats = newStats() + await spark.fetchCAR('http', '/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID', KNOWN_CID, stats) + assertEquals(stats.statusCode, 704, 'stats.statusCode') +}) + +test('fetchCAR fails with statusCode=705 (multiaddr has invalid http-path)', async () => { + const spark = new Spark() + const stats = newStats() + await spark.fetchCAR('http', '/dns/meridian.space/http/http-path/invalid%path', KNOWN_CID, stats) + assertEquals(stats.statusCode, 705, 'stats.statusCode') +}) + test('fetchCAR fails with statusCode=801 (DNS error)', async () => { const spark = new Spark() const stats = newStats() @@ -194,20 +207,6 @@ test('fetchCAR fails with statusCode=802 (TCP connection refused)', async () => assertEquals(stats.statusCode, 802, 'stats.statusCode') }) -test('fetchCAR fails with statusCode=704 (multiaddr has too many parts)', async () => { - const spark = new Spark() - const stats = newStats() - await spark.fetchCAR('http', '/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID', KNOWN_CID, stats) - assertEquals(stats.statusCode, 704, 'stats.statusCode') -}) - -test('fetchCAR fails with statusCode=705 (multiaddr has unsupported http-path)', async () => { - const spark = new Spark() - const stats = newStats() - await spark.fetchCAR('http', '/dns/meridian.space/http/http-path/invalid%path', KNOWN_CID, stats) - assertEquals(stats.statusCode, 705, 'stats.statusCode') -}) - // TODO: // statusCode=901 - unsupported hash algorithm From ea58d347bdb63291b8a22d9ea103934dfed71325 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Sun, 23 Feb 2025 15:21:44 +0100 Subject: [PATCH 07/19] fmt --- test/spark.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/spark.js b/test/spark.js index 4e596fa..6849119 100644 --- a/test/spark.js +++ b/test/spark.js @@ -165,6 +165,7 @@ test('fetchCAR fails with statusCode=703 (scheme is not http/https)', async () = await spark.fetchCAR('http', '/ip4/1.2.3.4/tcp/80/ldap', KNOWN_CID, stats) assertEquals(stats.statusCode, 703, 'stats.statusCode') }) + test('fetchCAR fails with statusCode=704 (multiaddr has too many parts) - multiaddr without http-path', async () => { const spark = new Spark() const stats = newStats() From 99a13f1ce8009a7c8ad00135256f323d135e60a1 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Sun, 23 Feb 2025 15:29:15 +0100 Subject: [PATCH 08/19] fmt --- test/multiaddr.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/multiaddr.test.js b/test/multiaddr.test.js index 808df57..ad491d8 100644 --- a/test/multiaddr.test.js +++ b/test/multiaddr.test.js @@ -27,7 +27,7 @@ const ERROR_CASES = [ ['/ip4/127.0.0.1/udp/90', 'Cannot parse "/ip4/127.0.0.1/udp/90": unsupported protocol "udp"'], ['/ip4/127.0.0.1/tcp/8080/http/p2p/pubkey', 'Cannot parse "/ip4/127.0.0.1/tcp/8080/http/p2p/pubkey": too many parts'], // NOTE: This is a valid multiaddr value that we decided to not support yet. - ['/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID', 'Cannot parse "/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID": too many parts'], + ['/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID', 'Cannot parse "/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID": unsupported scheme "tcp"'], ['/dns/meridian.space/http/http-path/invalid%path', 'Cannot parse "/dns/meridian.space/http/http-path/invalid%path": unsupported http path'] ] From 5493824f46419d0285410eef02f3ce0a882c6dd9 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Sun, 23 Feb 2025 15:32:07 +0100 Subject: [PATCH 09/19] scheme --- test/spark.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/spark.js b/test/spark.js index 6849119..cd68869 100644 --- a/test/spark.js +++ b/test/spark.js @@ -173,11 +173,11 @@ test('fetchCAR fails with statusCode=704 (multiaddr has too many parts) - multia assertEquals(stats.statusCode, 704, 'stats.statusCode') }) -test('fetchCAR fails with statusCode=704 (multiaddr has too many parts) - multiaddr with http-path', async () => { +test('fetchCAR fails with statusCode=704 (scheme is not http/https) - multiaddr with http-path', async () => { const spark = new Spark() const stats = newStats() await spark.fetchCAR('http', '/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID', KNOWN_CID, stats) - assertEquals(stats.statusCode, 704, 'stats.statusCode') + assertEquals(stats.statusCode, 703, 'stats.statusCode') }) test('fetchCAR fails with statusCode=705 (multiaddr has invalid http-path)', async () => { From 1378dab1aac3f9f70bee711fec6a91815bbdbef4 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl <113891786+NikolasHaimerl@users.noreply.github.com> Date: Mon, 24 Feb 2025 06:47:02 +0100 Subject: [PATCH 10/19] Update lib/multiaddr.js Co-authored-by: Julian Gruber --- lib/multiaddr.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/multiaddr.js b/lib/multiaddr.js index c586b62..ee0b4bf 100644 --- a/lib/multiaddr.js +++ b/lib/multiaddr.js @@ -20,10 +20,8 @@ export function multiaddrToHttpUrl (addr) { ) } } else { - const ipProtocol = multiAddrParts.shift() - port = multiAddrParts.shift() - scheme = multiAddrParts.shift() - rest = multiAddrParts + let ipProtocol + ;[ipProtocol, port, scheme, ...rest] = multiAddrParts if (ipProtocol !== 'tcp') { throw Object.assign( From bb6a219722bf7647630bc24281a4890515b6c097 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl <113891786+NikolasHaimerl@users.noreply.github.com> Date: Mon, 24 Feb 2025 06:50:50 +0100 Subject: [PATCH 11/19] Update lib/multiaddr.js Co-authored-by: Julian Gruber --- lib/multiaddr.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/multiaddr.js b/lib/multiaddr.js index ee0b4bf..ec9c703 100644 --- a/lib/multiaddr.js +++ b/lib/multiaddr.js @@ -11,7 +11,8 @@ export function multiaddrToHttpUrl (addr) { rest = multiAddrParts try { // Remove leading slash and parse URI-encoded path - // If the http-path is empty both `.../http-path/` and `.../http-path` are valid, see https://github.com/multiformats/multiaddr/blob/cab92e8e6da2e70c5f1b8aa59976e71e6922b392/protocols/http-path.md#usage + // If the http-path is empty, both `.../http-path/` and `.../http-path` are valid. + // See https://github.com/multiformats/multiaddr/blob/cab92e8e6da2e70c5f1b8aa59976e71e6922b392/protocols/http-path.md#usage path = decodeURIComponent(httpPathMultiAddr.replace(/^\/+/, '')) } catch (err) { throw Object.assign( From 9f81087092cf17e090073d5bf68df66117e376d1 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl <113891786+NikolasHaimerl@users.noreply.github.com> Date: Mon, 24 Feb 2025 06:51:05 +0100 Subject: [PATCH 12/19] Update lib/multiaddr.js Co-authored-by: Julian Gruber --- lib/multiaddr.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/multiaddr.js b/lib/multiaddr.js index ec9c703..01e21d6 100644 --- a/lib/multiaddr.js +++ b/lib/multiaddr.js @@ -7,8 +7,7 @@ export function multiaddrToHttpUrl (addr) { const [, hostType, hostValue, ...multiAddrParts] = multiAddr.split('/') let scheme, path, rest, port if (addr.includes('/http-path')) { - scheme = multiAddrParts.shift() - rest = multiAddrParts + [scheme, ...rest] = multiAddrParts try { // Remove leading slash and parse URI-encoded path // If the http-path is empty, both `.../http-path/` and `.../http-path` are valid. From 0abebbd255436c7a074115a132d1bf25815ffcc9 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl <113891786+NikolasHaimerl@users.noreply.github.com> Date: Mon, 24 Feb 2025 06:51:28 +0100 Subject: [PATCH 13/19] Update lib/multiaddr.js Co-authored-by: Julian Gruber --- lib/multiaddr.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/multiaddr.js b/lib/multiaddr.js index 01e21d6..898f25f 100644 --- a/lib/multiaddr.js +++ b/lib/multiaddr.js @@ -12,7 +12,9 @@ export function multiaddrToHttpUrl (addr) { // Remove leading slash and parse URI-encoded path // If the http-path is empty, both `.../http-path/` and `.../http-path` are valid. // See https://github.com/multiformats/multiaddr/blob/cab92e8e6da2e70c5f1b8aa59976e71e6922b392/protocols/http-path.md#usage - path = decodeURIComponent(httpPathMultiAddr.replace(/^\/+/, '')) + path = httpPathMultiAddr === '/' + ? '' + : decodeURIComponent(httpPathMultiAddr) } catch (err) { throw Object.assign( new Error(`Cannot parse "${addr}": unsupported http path`, { cause: err }), From 25b53e6f16b6f2c190de4831711098c7fd657b50 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Mon, 24 Feb 2025 08:54:07 +0100 Subject: [PATCH 14/19] fmt --- lib/multiaddr.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/multiaddr.js b/lib/multiaddr.js index 898f25f..d946db5 100644 --- a/lib/multiaddr.js +++ b/lib/multiaddr.js @@ -12,9 +12,8 @@ export function multiaddrToHttpUrl (addr) { // Remove leading slash and parse URI-encoded path // If the http-path is empty, both `.../http-path/` and `.../http-path` are valid. // See https://github.com/multiformats/multiaddr/blob/cab92e8e6da2e70c5f1b8aa59976e71e6922b392/protocols/http-path.md#usage - path = httpPathMultiAddr === '/' - ? '' - : decodeURIComponent(httpPathMultiAddr) + path = decodeURIComponent(httpPathMultiAddr.startsWith("/") ? httpPathMultiAddr.substring(1) : httpPathMultiAddr) + console.log("Path: ", path) } catch (err) { throw Object.assign( new Error(`Cannot parse "${addr}": unsupported http path`, { cause: err }), From 7e0009bf9649c518425ff14eea2fdfa46a109bc8 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Mon, 24 Feb 2025 08:55:48 +0100 Subject: [PATCH 15/19] lint --- lib/multiaddr.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/multiaddr.js b/lib/multiaddr.js index d946db5..400ee94 100644 --- a/lib/multiaddr.js +++ b/lib/multiaddr.js @@ -12,8 +12,7 @@ export function multiaddrToHttpUrl (addr) { // Remove leading slash and parse URI-encoded path // If the http-path is empty, both `.../http-path/` and `.../http-path` are valid. // See https://github.com/multiformats/multiaddr/blob/cab92e8e6da2e70c5f1b8aa59976e71e6922b392/protocols/http-path.md#usage - path = decodeURIComponent(httpPathMultiAddr.startsWith("/") ? httpPathMultiAddr.substring(1) : httpPathMultiAddr) - console.log("Path: ", path) + path = decodeURIComponent(httpPathMultiAddr.startsWith('/') ? httpPathMultiAddr.substring(1) : httpPathMultiAddr) } catch (err) { throw Object.assign( new Error(`Cannot parse "${addr}": unsupported http path`, { cause: err }), From 44b44fd84f91d764c0addcbadec8728f364e298c Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Mon, 24 Feb 2025 08:58:57 +0100 Subject: [PATCH 16/19] test naming --- test/spark.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/spark.js b/test/spark.js index cd68869..7dd585e 100644 --- a/test/spark.js +++ b/test/spark.js @@ -159,25 +159,25 @@ test('fetchCAR fails with statusCode=702 (protocol is not tcp)', async () => { assertEquals(stats.statusCode, 702, 'stats.statusCode') }) -test('fetchCAR fails with statusCode=703 (scheme is not http/https)', async () => { +test('fetchCAR fails with statusCode=703 (scheme is not http/https) - multiaddr without http-path', async () => { const spark = new Spark() const stats = newStats() await spark.fetchCAR('http', '/ip4/1.2.3.4/tcp/80/ldap', KNOWN_CID, stats) assertEquals(stats.statusCode, 703, 'stats.statusCode') }) -test('fetchCAR fails with statusCode=704 (multiaddr has too many parts) - multiaddr without http-path', async () => { +test('fetchCAR fails with statusCode=703 (scheme is not http/https) - multiaddr with http-path', async () => { const spark = new Spark() const stats = newStats() - await spark.fetchCAR('http', '/ip4/1.2.3.4/tcp/80/http/p2p/pubkey', KNOWN_CID, stats) - assertEquals(stats.statusCode, 704, 'stats.statusCode') + await spark.fetchCAR('http', '/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID', KNOWN_CID, stats) + assertEquals(stats.statusCode, 703, 'stats.statusCode') }) -test('fetchCAR fails with statusCode=704 (scheme is not http/https) - multiaddr with http-path', async () => { +test('fetchCAR fails with statusCode=704 (multiaddr has too many parts)', async () => { const spark = new Spark() const stats = newStats() - await spark.fetchCAR('http', '/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID', KNOWN_CID, stats) - assertEquals(stats.statusCode, 703, 'stats.statusCode') + await spark.fetchCAR('http', '/ip4/1.2.3.4/tcp/80/http/p2p/pubkey', KNOWN_CID, stats) + assertEquals(stats.statusCode, 704, 'stats.statusCode') }) test('fetchCAR fails with statusCode=705 (multiaddr has invalid http-path)', async () => { From 55655217edc6696ce3451943d44368424031b1cd Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl <113891786+NikolasHaimerl@users.noreply.github.com> Date: Mon, 24 Feb 2025 12:49:34 +0100 Subject: [PATCH 17/19] Update lib/multiaddr.js Co-authored-by: Julian Gruber --- lib/multiaddr.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/multiaddr.js b/lib/multiaddr.js index 400ee94..231ad01 100644 --- a/lib/multiaddr.js +++ b/lib/multiaddr.js @@ -10,7 +10,6 @@ export function multiaddrToHttpUrl (addr) { [scheme, ...rest] = multiAddrParts try { // Remove leading slash and parse URI-encoded path - // If the http-path is empty, both `.../http-path/` and `.../http-path` are valid. // See https://github.com/multiformats/multiaddr/blob/cab92e8e6da2e70c5f1b8aa59976e71e6922b392/protocols/http-path.md#usage path = decodeURIComponent(httpPathMultiAddr.startsWith('/') ? httpPathMultiAddr.substring(1) : httpPathMultiAddr) } catch (err) { From e1ae5e11349d6168f3010e12aee0dc2f88a8d92b Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl <113891786+NikolasHaimerl@users.noreply.github.com> Date: Mon, 24 Feb 2025 12:52:38 +0100 Subject: [PATCH 18/19] Update lib/multiaddr.js Co-authored-by: Julian Gruber --- lib/multiaddr.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/multiaddr.js b/lib/multiaddr.js index 231ad01..64d9fc8 100644 --- a/lib/multiaddr.js +++ b/lib/multiaddr.js @@ -11,7 +11,7 @@ export function multiaddrToHttpUrl (addr) { try { // Remove leading slash and parse URI-encoded path // See https://github.com/multiformats/multiaddr/blob/cab92e8e6da2e70c5f1b8aa59976e71e6922b392/protocols/http-path.md#usage - path = decodeURIComponent(httpPathMultiAddr.startsWith('/') ? httpPathMultiAddr.substring(1) : httpPathMultiAddr) + path = decodeURIComponent(httpPathMultiAddr.substring(1)) } catch (err) { throw Object.assign( new Error(`Cannot parse "${addr}": unsupported http path`, { cause: err }), From 91f80e3c70d97cf59179b53dfa12a00f5ddc2ed1 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl <113891786+NikolasHaimerl@users.noreply.github.com> Date: Mon, 24 Feb 2025 14:53:24 +0100 Subject: [PATCH 19/19] Update test/spark.js Co-authored-by: Julian Gruber --- test/spark.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spark.js b/test/spark.js index 7dd585e..3eca54c 100644 --- a/test/spark.js +++ b/test/spark.js @@ -166,7 +166,7 @@ test('fetchCAR fails with statusCode=703 (scheme is not http/https) - multiaddr assertEquals(stats.statusCode, 703, 'stats.statusCode') }) -test('fetchCAR fails with statusCode=703 (scheme is not http/https) - multiaddr with http-path', async () => { +test('fetchCAR fails with statusCode=703 (scheme is not supported) - multiaddr with http-path', async () => { const spark = new Spark() const stats = newStats() await spark.fetchCAR('http', '/dns/meridian.space/tcp/8080/http/http-path/%2Fipni-provider%2FproviderID', KNOWN_CID, stats)