From 8e025e70af0475e89b867dac8f6ff58ab47c2ce0 Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Mon, 26 May 2025 12:46:03 +0100 Subject: [PATCH 1/2] feat: support proto encoding --- src/api.ts | 1 + src/index.js | 22 +++++- test/index.test.js | 179 +++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 187 insertions(+), 15 deletions(-) diff --git a/src/api.ts b/src/api.ts index 58b7b75..9f93a6f 100644 --- a/src/api.ts +++ b/src/api.ts @@ -3,6 +3,7 @@ import { Multiaddr } from '@multiformats/multiaddr' export interface ProviderHint { multiaddr: Multiaddr + protos?: string[] } export type { CID, Multiaddr } diff --git a/src/index.js b/src/index.js index a6e22ec..d917dc4 100644 --- a/src/index.js +++ b/src/index.js @@ -36,6 +36,10 @@ export function createUri({ base, path, providers = [] }) { const baseParts = provider.multiaddr.toString().split('/') const hintParts = [...baseParts] + for (const proto of provider.protos || []) { + if (proto) hintParts.push('retrieval', proto) + } + const hint = '/' + hintParts.filter(Boolean).join('/') url.searchParams.append('provider', hint) } @@ -79,9 +83,25 @@ export function parseQueryString(query) { for (const val of searchParams.getAll('provider')) { if (!val.startsWith('/')) continue + const protoParts = val.split('/').filter(Boolean) + /** @type {string[]} */ + const protos = [] + + for (let i = 0; i < protoParts.length; ) { + if (protoParts[i] === 'retrieval') { + i++ + if (i < protoParts.length) { + protos.push(protoParts[i]) + i++ + } + } else { + i++ + } + } + try { const m = multiaddr(val) - providers.push({ multiaddr: m }) + providers.push({ multiaddr: m, protos }) } catch { // Skip malformed multiaddrs continue diff --git a/test/index.test.js b/test/index.test.js index 005b334..7f8a621 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -30,12 +30,44 @@ describe('creates and parses provider-hinted-uris', () => { assert.deepStrictEqual(parsed.providers, []) }) + it('parses provider hint with multiple retrieval markers', () => { + const base = `https://example.com/ipfs/${cidStr}` + const url = new URL(base) + const appendedMultiaddr = `${maddr.toString()}/retrieval/http/retrieval/bitswap` + url.searchParams.append('provider', appendedMultiaddr) + const parsed = parseUri(url.toString()) + + assert.strictEqual(parsed.providers.length, 1) + assert.strictEqual( + parsed.providers[0].multiaddr.toString(), + appendedMultiaddr + ) + assert.deepStrictEqual(parsed.providers[0].protos, ['http', 'bitswap']) + }) + it('throws on ambiguous subdomain + path format', () => { const uri = `https://${cidStr}.ipfs.dweb.link/ipfs/${cidStr}` assert.throws(() => parseUri(uri), /ambiguous/) }) - it('creates URI with provider hints', () => { + it('creates URI with provider hints (no protos)', () => { + const base = `https://example.com/ipfs/${cidStr}` + const uri = createUri({ + base, + providers: [{ multiaddr: maddr, protos: [] }], + }) + + const parsed = parseUri(uri.toString()) + assert.strictEqual(parsed.cid.toString(), cidStr) + assert.strictEqual(parsed.providers.length, 1) + assert.strictEqual( + parsed.providers[0].multiaddr.toString(), + maddr.toString() + ) + assert.deepStrictEqual(parsed.providers[0].protos, []) + }) + + it('creates URI with provider hints (undefined protos)', () => { const base = `https://example.com/ipfs/${cidStr}` const uri = createUri({ base, @@ -49,9 +81,61 @@ describe('creates and parses provider-hinted-uris', () => { parsed.providers[0].multiaddr.toString(), maddr.toString() ) + assert.deepStrictEqual(parsed.providers[0].protos, []) + }) + + it('creates URI with provider hints (with protos)', () => { + const base = `https://example.com/ipfs/${cidStr}` + const protos = ['http', 'bitswap'] + const uri = createUri({ + base, + providers: [{ multiaddr: maddr, protos }], + }) + + const parsed = parseUri(uri.toString()) + assert.strictEqual(parsed.cid.toString(), cidStr) + assert.strictEqual(parsed.providers.length, 1) + assert.strictEqual( + parsed.providers[0].multiaddr.toString(), + `${maddr.toString()}/retrieval/http/retrieval/bitswap` + ) + assert.deepStrictEqual(parsed.providers[0].protos, protos) + }) + + it('creates URI with multiple provider hints (mixed protos)', () => { + const base = `https://example.com/ipfs/${cidStr}` + const providers = [ + { multiaddr: multiaddr('/ip4/1.2.3.4/tcp/1234/ws'), protos: ['bitswap'] }, + { multiaddr: multiaddr('/ip4/5.6.7.8/tcp/443/https'), protos: ['http'] }, + { multiaddr: multiaddr('/dnsaddr/provider.example.com'), protos: [] }, + ] + + const uri = createUri({ base, providers }) + const parsed = parseUri(uri.toString()) + + assert.strictEqual(parsed.cid.toString(), cidStr) + assert.strictEqual(parsed.providers.length, 3) + + assert.strictEqual( + parsed.providers[0].multiaddr.toString(), + `${providers[0].multiaddr}/retrieval/bitswap` + ) + assert.deepStrictEqual(parsed.providers[0].protos, ['bitswap']) + + assert.strictEqual( + parsed.providers[1].multiaddr.toString(), + `${providers[1].multiaddr}/retrieval/http` + ) + assert.deepStrictEqual(parsed.providers[1].protos, ['http']) + + assert.strictEqual( + parsed.providers[2].multiaddr.toString(), + providers[2].multiaddr.toString() + ) + assert.deepStrictEqual(parsed.providers[2].protos, []) }) - it('parses provider with trailing retrieval', () => { + it('parses provider with trailing retrieval and no protocol', () => { const ma = '/ip4/1.2.3.4/tcp/1234/retrieval' const base = `https://example.com/ipfs/${cidStr}` const url = new URL(base) @@ -60,18 +144,46 @@ describe('creates and parses provider-hinted-uris', () => { assert.strictEqual(parsed.providers.length, 0) }) + it('parses retrieval hint with unknown protocol', () => { + const ma = '/ip4/1.2.3.4/tcp/1234/retrieval/magicretrieval' + const base = `https://example.com/ipfs/${cidStr}` + const url = new URL(base) + url.searchParams.append('provider', ma) + const parsed = parseUri(url.toString()) + assert.strictEqual(parsed.providers.length, 1) + assert.deepStrictEqual(parsed.providers[0].protos, ['magicretrieval']) + }) + it('handles multiple provider hints, some invalid', () => { const base = `https://example.com/ipfs/${cidStr}` - const appendedMultiaddr = `${maddr.toString()}` + const appendedMultiaddr = `${maddr.toString()}/retrieval/bitswap` const url = new URL(base) url.searchParams.append('provider', appendedMultiaddr) url.searchParams.append('provider', 'bad-ma') + const appendedMultiaddr2 = '/ip4/5.6.7.8/tcp/4321/https/retrieval/http' + url.searchParams.append('provider', appendedMultiaddr2) const parsed = parseUri(url.toString()) - assert.strictEqual(parsed.providers.length, 1) + assert.strictEqual(parsed.providers.length, 2) assert.strictEqual( parsed.providers[0].multiaddr.toString(), appendedMultiaddr ) + assert.deepStrictEqual(parsed.providers[0].protos, ['bitswap']) + assert.strictEqual( + parsed.providers[1].multiaddr.toString(), + appendedMultiaddr2 + ) + assert.deepStrictEqual(parsed.providers[1].protos, ['http']) + }) + + it('ignores invalid multiaddr hints during parsing', () => { + const base = `https://example.com/ipfs/${cidStr}` + const url = new URL(base) + // Add a malformed multiaddr as a provider hint + url.searchParams.append('provider', '/not/a/real/multiaddr/retrieval/http') + const parsed = parseUri(url.toString()) + assert.deepStrictEqual(parsed.cid.toString(), cidStr) + assert.deepStrictEqual(parsed.providers, []) }) it('ignores empty provider string', () => { @@ -113,11 +225,12 @@ describe('creates and parses provider-hinted-uris', () => { providers: [ { multiaddr: maddr, + protos: ['http', 'bitswap'], }, ], }) - const expectedProvider = `${maddr.toString()}` + const expectedProvider = `${maddr.toString()}/retrieval/http/retrieval/bitswap` const parsed = parseUri(url.toString()) assert.strictEqual(parsed.cid.toString(), cidStr) @@ -127,6 +240,7 @@ describe('creates and parses provider-hinted-uris', () => { parsed.providers[0].multiaddr.toString(), expectedProvider ) + assert.deepStrictEqual(parsed.providers[0].protos, ['http', 'bitswap']) }) it('adds leading slash if path does not start with /', () => { @@ -190,17 +304,23 @@ describe('creates and parses provider-hinted-uris', () => { describe('parseQueryString', () => { const maddr = multiaddr('/ip4/1.2.3.4/tcp/1234') - it('parses single provider hint', () => { - const input = `?provider=${encodeURIComponent(`${maddr.toString()}`)}` + it('parses single provider hint with multiple retrieval markers', () => { + const input = `?provider=${encodeURIComponent( + `${maddr.toString()}/retrieval/http/retrieval/bitswap` + )}` const providers = parseQueryString(input) assert.strictEqual(providers.length, 1) - assert.strictEqual(providers[0].multiaddr.toString(), `${maddr.toString()}`) + assert.strictEqual( + providers[0].multiaddr.toString(), + `${maddr.toString()}/retrieval/http/retrieval/bitswap` + ) + assert.deepStrictEqual(providers[0].protos, ['http', 'bitswap']) }) it('parses multiple valid provider hints', () => { const hints = [ - `${maddr.toString()}`, - '/ip4/5.6.7.8/tcp/4321/https', + `${maddr.toString()}/retrieval/http`, + '/ip4/5.6.7.8/tcp/4321/https/retrieval/bitswap', '/dnsaddr/provider.example.com', ] const query = hints @@ -210,18 +330,24 @@ describe('parseQueryString', () => { assert.strictEqual(providers.length, 3) assert.strictEqual(providers[0].multiaddr.toString(), hints[0]) + assert.deepStrictEqual(providers[0].protos, ['http']) + assert.strictEqual(providers[1].multiaddr.toString(), hints[1]) + assert.deepStrictEqual(providers[1].protos, ['bitswap']) + assert.strictEqual(providers[2].multiaddr.toString(), hints[2]) + assert.deepStrictEqual(providers[2].protos, []) }) it('ignores malformed multiaddrs', () => { - const valid = `${maddr.toString()}` + const valid = `${maddr.toString()}/retrieval/http` const query = `provider=${encodeURIComponent( valid )}&provider=not-a-ma&provider=/gibber/ish` const providers = parseQueryString(`?${query}`) assert.strictEqual(providers.length, 1) assert.strictEqual(providers[0].multiaddr.toString(), valid) + assert.deepStrictEqual(providers[0].protos, ['http']) }) it('ignores provider values not starting with "/"', () => { @@ -232,16 +358,40 @@ describe('parseQueryString', () => { providers[0].multiaddr.toString(), '/ip4/1.1.1.1/tcp/4001' ) + assert.deepStrictEqual(providers[0].protos, []) }) it('ignores empty provider values', () => { - const query = 'provider=&provider=/ip4/2.2.2.2/tcp/1234' + const query = 'provider=&provider=/ip4/2.2.2.2/tcp/1234/retrieval/bitswap' const providers = parseQueryString(`?${query}`) assert.strictEqual(providers.length, 1) assert.strictEqual( providers[0].multiaddr.toString(), - '/ip4/2.2.2.2/tcp/1234' + '/ip4/2.2.2.2/tcp/1234/retrieval/bitswap' ) + assert.deepStrictEqual(providers[0].protos, ['bitswap']) + }) + + it('supports unknown retrieval protocols', () => { + const input = `?provider=${encodeURIComponent( + `${maddr.toString()}/retrieval/magic` + )}` + + const providers = parseQueryString(input) + assert.strictEqual(providers.length, 1) + assert.strictEqual( + providers[0].multiaddr.toString(), + `${maddr.toString()}/retrieval/magic` + ) + assert.deepStrictEqual(providers[0].protos, ['magic']) + }) + + it('ignores trailing /retrieval without proto', () => { + const input = `?provider=${encodeURIComponent( + `${maddr.toString()}/retrieval` + )}` + const providers = parseQueryString(input) + assert.strictEqual(providers.length, 0) }) it('returns empty array if no provider params', () => { @@ -250,10 +400,11 @@ describe('parseQueryString', () => { }) it('decodes percent-encoded multiaddrs correctly', () => { - const raw = `${maddr.toString()}` + const raw = `${maddr.toString()}/retrieval/bitswap` const encoded = encodeURIComponent(raw) const providers = parseQueryString(`?provider=${encoded}`) assert.strictEqual(providers.length, 1) assert.strictEqual(providers[0].multiaddr.toString(), raw) + assert.deepStrictEqual(providers[0].protos, ['bitswap']) }) }) From 46e04b42ad536249605852d47a812507165017ca Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Thu, 5 Jun 2025 16:15:23 +0200 Subject: [PATCH 2/2] fix: rename retrieval to tag --- package.json | 2 +- pnpm-lock.yaml | 30 +++++------ src/api.ts | 4 +- src/index.js | 16 +++--- test/index.test.js | 122 ++++++++++++++++++++++----------------------- 5 files changed, 86 insertions(+), 88 deletions(-) diff --git a/package.json b/package.json index 9cc6971..ca6ce85 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "test:browser": "playwright-test --runner mocha 'test/**/!(*.node).test.js'" }, "dependencies": { - "@multiformats/multiaddr": "^12.4.0", + "@vascosantos/multiaddr": "^12.4.2", "multiformats": "^13.3.6" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b346a6d..36c10d4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,9 +8,9 @@ importers: .: dependencies: - '@multiformats/multiaddr': - specifier: ^12.4.0 - version: 12.4.0 + '@vascosantos/multiaddr': + specifier: ^12.4.2 + version: 12.4.2 multiformats: specifier: ^13.3.6 version: 13.3.6 @@ -348,9 +348,6 @@ packages: '@multiformats/dns@1.0.6': resolution: {integrity: sha512-nt/5UqjMPtyvkG9BQYdJ4GfLK3nMqGpFZOzf4hAmIa0sJh2LlS9YKXZ4FgwBDsaHvzZqR/rUFIywIc7pkHNNuw==} - '@multiformats/multiaddr@12.4.0': - resolution: {integrity: sha512-FL7yBTLijJ5JkO044BGb2msf+uJLrwpD6jD6TkXlbjA9N12+18HT40jvd4o5vL4LOJMc86dPX6tGtk/uI9kYKg==} - '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -476,6 +473,9 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@vascosantos/multiaddr@12.4.2': + resolution: {integrity: sha512-0nNO3eBXtBtKKc4FgcnINHK5gdDm9j5H4TwK9dLVvfjMN+aX5UBBB58GxvV4bFlsg2JuC9895uhlJPNN88j7Eg==} + '@vue/compiler-core@3.5.14': resolution: {integrity: sha512-k7qMHMbKvoCXIxPhquKQVw3Twid3Kg4s7+oYURxLGRd56LiuHJVrvFKI4fm2AM3c8apqODPfVJGoh8nePbXMRA==} @@ -2640,15 +2640,6 @@ snapshots: progress-events: 1.0.1 uint8arrays: 5.1.0 - '@multiformats/multiaddr@12.4.0': - dependencies: - '@chainsafe/is-ip': 2.1.0 - '@chainsafe/netmask': 2.0.0 - '@multiformats/dns': 1.0.6 - multiformats: 13.3.6 - uint8-varint: 2.0.4 - uint8arrays: 5.1.0 - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2786,6 +2777,15 @@ snapshots: '@ungap/structured-clone@1.3.0': {} + '@vascosantos/multiaddr@12.4.2': + dependencies: + '@chainsafe/is-ip': 2.1.0 + '@chainsafe/netmask': 2.0.0 + '@multiformats/dns': 1.0.6 + multiformats: 13.3.6 + uint8-varint: 2.0.4 + uint8arrays: 5.1.0 + '@vue/compiler-core@3.5.14': dependencies: '@babel/parser': 7.27.2 diff --git a/src/api.ts b/src/api.ts index 9f93a6f..f22faac 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,9 +1,9 @@ import { CID } from 'multiformats/cid' -import { Multiaddr } from '@multiformats/multiaddr' +import { Multiaddr } from '@vascosantos/multiaddr' export interface ProviderHint { multiaddr: Multiaddr - protos?: string[] + tags?: string[] } export type { CID, Multiaddr } diff --git a/src/index.js b/src/index.js index d917dc4..ff7d813 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ import * as API from './api.js' -import { multiaddr, isMultiaddr } from '@multiformats/multiaddr' +import { multiaddr, isMultiaddr } from '@vascosantos/multiaddr' import { CID } from 'multiformats/cid' /** @@ -36,8 +36,8 @@ export function createUri({ base, path, providers = [] }) { const baseParts = provider.multiaddr.toString().split('/') const hintParts = [...baseParts] - for (const proto of provider.protos || []) { - if (proto) hintParts.push('retrieval', proto) + for (const tag of provider.tags || []) { + if (tag) hintParts.push('tag', tag) } const hint = '/' + hintParts.filter(Boolean).join('/') @@ -49,7 +49,7 @@ export function createUri({ base, path, providers = [] }) { /** * Parse a provider-hinted URI into a CID and structured provider hints, - * preserving the full multiaddr including `/retrieval/` segments. + * preserving the full multiaddr including `/tag/` segments. * * @param {string} uri * @returns {{ cid: API.CID, providers: API.ProviderHint[], path: string, protocol: string }} @@ -85,13 +85,13 @@ export function parseQueryString(query) { const protoParts = val.split('/').filter(Boolean) /** @type {string[]} */ - const protos = [] + const tags = [] for (let i = 0; i < protoParts.length; ) { - if (protoParts[i] === 'retrieval') { + if (protoParts[i] === 'tag') { i++ if (i < protoParts.length) { - protos.push(protoParts[i]) + tags.push(protoParts[i]) i++ } } else { @@ -101,7 +101,7 @@ export function parseQueryString(query) { try { const m = multiaddr(val) - providers.push({ multiaddr: m, protos }) + providers.push({ multiaddr: m, tags }) } catch { // Skip malformed multiaddrs continue diff --git a/test/index.test.js b/test/index.test.js index 7f8a621..7c9307d 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,7 +1,7 @@ /* global console */ import assert from 'assert' -import { multiaddr } from '@multiformats/multiaddr' +import { multiaddr } from '@vascosantos/multiaddr' import { createUri, parseUri, parseQueryString } from '../src/index.js' @@ -30,10 +30,10 @@ describe('creates and parses provider-hinted-uris', () => { assert.deepStrictEqual(parsed.providers, []) }) - it('parses provider hint with multiple retrieval markers', () => { + it('parses provider hint with multiple tag markers', () => { const base = `https://example.com/ipfs/${cidStr}` const url = new URL(base) - const appendedMultiaddr = `${maddr.toString()}/retrieval/http/retrieval/bitswap` + const appendedMultiaddr = `${maddr.toString()}/tag/http/tag/bitswap` url.searchParams.append('provider', appendedMultiaddr) const parsed = parseUri(url.toString()) @@ -42,7 +42,7 @@ describe('creates and parses provider-hinted-uris', () => { parsed.providers[0].multiaddr.toString(), appendedMultiaddr ) - assert.deepStrictEqual(parsed.providers[0].protos, ['http', 'bitswap']) + assert.deepStrictEqual(parsed.providers[0].tags, ['http', 'bitswap']) }) it('throws on ambiguous subdomain + path format', () => { @@ -50,11 +50,11 @@ describe('creates and parses provider-hinted-uris', () => { assert.throws(() => parseUri(uri), /ambiguous/) }) - it('creates URI with provider hints (no protos)', () => { + it('creates URI with provider hints (no tags)', () => { const base = `https://example.com/ipfs/${cidStr}` const uri = createUri({ base, - providers: [{ multiaddr: maddr, protos: [] }], + providers: [{ multiaddr: maddr, tags: [] }], }) const parsed = parseUri(uri.toString()) @@ -64,10 +64,10 @@ describe('creates and parses provider-hinted-uris', () => { parsed.providers[0].multiaddr.toString(), maddr.toString() ) - assert.deepStrictEqual(parsed.providers[0].protos, []) + assert.deepStrictEqual(parsed.providers[0].tags, []) }) - it('creates URI with provider hints (undefined protos)', () => { + it('creates URI with provider hints (undefined tags)', () => { const base = `https://example.com/ipfs/${cidStr}` const uri = createUri({ base, @@ -81,15 +81,15 @@ describe('creates and parses provider-hinted-uris', () => { parsed.providers[0].multiaddr.toString(), maddr.toString() ) - assert.deepStrictEqual(parsed.providers[0].protos, []) + assert.deepStrictEqual(parsed.providers[0].tags, []) }) - it('creates URI with provider hints (with protos)', () => { + it('creates URI with provider hints (with tags)', () => { const base = `https://example.com/ipfs/${cidStr}` - const protos = ['http', 'bitswap'] + const tags = ['http', 'bitswap'] const uri = createUri({ base, - providers: [{ multiaddr: maddr, protos }], + providers: [{ multiaddr: maddr, tags }], }) const parsed = parseUri(uri.toString()) @@ -97,17 +97,17 @@ describe('creates and parses provider-hinted-uris', () => { assert.strictEqual(parsed.providers.length, 1) assert.strictEqual( parsed.providers[0].multiaddr.toString(), - `${maddr.toString()}/retrieval/http/retrieval/bitswap` + `${maddr.toString()}/tag/http/tag/bitswap` ) - assert.deepStrictEqual(parsed.providers[0].protos, protos) + assert.deepStrictEqual(parsed.providers[0].tags, tags) }) - it('creates URI with multiple provider hints (mixed protos)', () => { + it('creates URI with multiple provider hints (mixed tags)', () => { const base = `https://example.com/ipfs/${cidStr}` const providers = [ - { multiaddr: multiaddr('/ip4/1.2.3.4/tcp/1234/ws'), protos: ['bitswap'] }, - { multiaddr: multiaddr('/ip4/5.6.7.8/tcp/443/https'), protos: ['http'] }, - { multiaddr: multiaddr('/dnsaddr/provider.example.com'), protos: [] }, + { multiaddr: multiaddr('/ip4/1.2.3.4/tcp/1234/ws'), tags: ['bitswap'] }, + { multiaddr: multiaddr('/ip4/5.6.7.8/tcp/443/https'), tags: ['http'] }, + { multiaddr: multiaddr('/dnsaddr/provider.example.com'), tags: [] }, ] const uri = createUri({ base, providers }) @@ -118,25 +118,25 @@ describe('creates and parses provider-hinted-uris', () => { assert.strictEqual( parsed.providers[0].multiaddr.toString(), - `${providers[0].multiaddr}/retrieval/bitswap` + `${providers[0].multiaddr}/tag/bitswap` ) - assert.deepStrictEqual(parsed.providers[0].protos, ['bitswap']) + assert.deepStrictEqual(parsed.providers[0].tags, ['bitswap']) assert.strictEqual( parsed.providers[1].multiaddr.toString(), - `${providers[1].multiaddr}/retrieval/http` + `${providers[1].multiaddr}/tag/http` ) - assert.deepStrictEqual(parsed.providers[1].protos, ['http']) + assert.deepStrictEqual(parsed.providers[1].tags, ['http']) assert.strictEqual( parsed.providers[2].multiaddr.toString(), providers[2].multiaddr.toString() ) - assert.deepStrictEqual(parsed.providers[2].protos, []) + assert.deepStrictEqual(parsed.providers[2].tags, []) }) - it('parses provider with trailing retrieval and no protocol', () => { - const ma = '/ip4/1.2.3.4/tcp/1234/retrieval' + it('parses provider with trailing tag and no protocol', () => { + const ma = '/ip4/1.2.3.4/tcp/1234/tag' const base = `https://example.com/ipfs/${cidStr}` const url = new URL(base) url.searchParams.append('provider', ma) @@ -144,23 +144,23 @@ describe('creates and parses provider-hinted-uris', () => { assert.strictEqual(parsed.providers.length, 0) }) - it('parses retrieval hint with unknown protocol', () => { - const ma = '/ip4/1.2.3.4/tcp/1234/retrieval/magicretrieval' + it('parses tag hint with unknown protocol', () => { + const ma = '/ip4/1.2.3.4/tcp/1234/tag/magictag' const base = `https://example.com/ipfs/${cidStr}` const url = new URL(base) url.searchParams.append('provider', ma) const parsed = parseUri(url.toString()) assert.strictEqual(parsed.providers.length, 1) - assert.deepStrictEqual(parsed.providers[0].protos, ['magicretrieval']) + assert.deepStrictEqual(parsed.providers[0].tags, ['magictag']) }) it('handles multiple provider hints, some invalid', () => { const base = `https://example.com/ipfs/${cidStr}` - const appendedMultiaddr = `${maddr.toString()}/retrieval/bitswap` + const appendedMultiaddr = `${maddr.toString()}/tag/bitswap` const url = new URL(base) url.searchParams.append('provider', appendedMultiaddr) url.searchParams.append('provider', 'bad-ma') - const appendedMultiaddr2 = '/ip4/5.6.7.8/tcp/4321/https/retrieval/http' + const appendedMultiaddr2 = '/ip4/5.6.7.8/tcp/4321/https/tag/http' url.searchParams.append('provider', appendedMultiaddr2) const parsed = parseUri(url.toString()) assert.strictEqual(parsed.providers.length, 2) @@ -168,19 +168,19 @@ describe('creates and parses provider-hinted-uris', () => { parsed.providers[0].multiaddr.toString(), appendedMultiaddr ) - assert.deepStrictEqual(parsed.providers[0].protos, ['bitswap']) + assert.deepStrictEqual(parsed.providers[0].tags, ['bitswap']) assert.strictEqual( parsed.providers[1].multiaddr.toString(), appendedMultiaddr2 ) - assert.deepStrictEqual(parsed.providers[1].protos, ['http']) + assert.deepStrictEqual(parsed.providers[1].tags, ['http']) }) it('ignores invalid multiaddr hints during parsing', () => { const base = `https://example.com/ipfs/${cidStr}` const url = new URL(base) // Add a malformed multiaddr as a provider hint - url.searchParams.append('provider', '/not/a/real/multiaddr/retrieval/http') + url.searchParams.append('provider', '/not/a/real/multiaddr/tag/http') const parsed = parseUri(url.toString()) assert.deepStrictEqual(parsed.cid.toString(), cidStr) assert.deepStrictEqual(parsed.providers, []) @@ -225,12 +225,12 @@ describe('creates and parses provider-hinted-uris', () => { providers: [ { multiaddr: maddr, - protos: ['http', 'bitswap'], + tags: ['http', 'bitswap'], }, ], }) - const expectedProvider = `${maddr.toString()}/retrieval/http/retrieval/bitswap` + const expectedProvider = `${maddr.toString()}/tag/http/tag/bitswap` const parsed = parseUri(url.toString()) assert.strictEqual(parsed.cid.toString(), cidStr) @@ -240,7 +240,7 @@ describe('creates and parses provider-hinted-uris', () => { parsed.providers[0].multiaddr.toString(), expectedProvider ) - assert.deepStrictEqual(parsed.providers[0].protos, ['http', 'bitswap']) + assert.deepStrictEqual(parsed.providers[0].tags, ['http', 'bitswap']) }) it('adds leading slash if path does not start with /', () => { @@ -294,7 +294,7 @@ describe('creates and parses provider-hinted-uris', () => { createUri({ base, /** @ts-expect-error */ - providers: [{ multiaddr: 'not-a-ma', protos: [] }], + providers: [{ multiaddr: 'not-a-ma', tags: [] }], }), /multiaddr must be a Multiaddr instance/ ) @@ -304,23 +304,23 @@ describe('creates and parses provider-hinted-uris', () => { describe('parseQueryString', () => { const maddr = multiaddr('/ip4/1.2.3.4/tcp/1234') - it('parses single provider hint with multiple retrieval markers', () => { + it('parses single provider hint with multiple tag markers', () => { const input = `?provider=${encodeURIComponent( - `${maddr.toString()}/retrieval/http/retrieval/bitswap` + `${maddr.toString()}/tag/http/tag/bitswap` )}` const providers = parseQueryString(input) assert.strictEqual(providers.length, 1) assert.strictEqual( providers[0].multiaddr.toString(), - `${maddr.toString()}/retrieval/http/retrieval/bitswap` + `${maddr.toString()}/tag/http/tag/bitswap` ) - assert.deepStrictEqual(providers[0].protos, ['http', 'bitswap']) + assert.deepStrictEqual(providers[0].tags, ['http', 'bitswap']) }) it('parses multiple valid provider hints', () => { const hints = [ - `${maddr.toString()}/retrieval/http`, - '/ip4/5.6.7.8/tcp/4321/https/retrieval/bitswap', + `${maddr.toString()}/tag/http`, + '/ip4/5.6.7.8/tcp/4321/https/tag/bitswap', '/dnsaddr/provider.example.com', ] const query = hints @@ -330,24 +330,24 @@ describe('parseQueryString', () => { assert.strictEqual(providers.length, 3) assert.strictEqual(providers[0].multiaddr.toString(), hints[0]) - assert.deepStrictEqual(providers[0].protos, ['http']) + assert.deepStrictEqual(providers[0].tags, ['http']) assert.strictEqual(providers[1].multiaddr.toString(), hints[1]) - assert.deepStrictEqual(providers[1].protos, ['bitswap']) + assert.deepStrictEqual(providers[1].tags, ['bitswap']) assert.strictEqual(providers[2].multiaddr.toString(), hints[2]) - assert.deepStrictEqual(providers[2].protos, []) + assert.deepStrictEqual(providers[2].tags, []) }) it('ignores malformed multiaddrs', () => { - const valid = `${maddr.toString()}/retrieval/http` + const valid = `${maddr.toString()}/tag/http` const query = `provider=${encodeURIComponent( valid )}&provider=not-a-ma&provider=/gibber/ish` const providers = parseQueryString(`?${query}`) assert.strictEqual(providers.length, 1) assert.strictEqual(providers[0].multiaddr.toString(), valid) - assert.deepStrictEqual(providers[0].protos, ['http']) + assert.deepStrictEqual(providers[0].tags, ['http']) }) it('ignores provider values not starting with "/"', () => { @@ -358,38 +358,36 @@ describe('parseQueryString', () => { providers[0].multiaddr.toString(), '/ip4/1.1.1.1/tcp/4001' ) - assert.deepStrictEqual(providers[0].protos, []) + assert.deepStrictEqual(providers[0].tags, []) }) it('ignores empty provider values', () => { - const query = 'provider=&provider=/ip4/2.2.2.2/tcp/1234/retrieval/bitswap' + const query = 'provider=&provider=/ip4/2.2.2.2/tcp/1234/tag/bitswap' const providers = parseQueryString(`?${query}`) assert.strictEqual(providers.length, 1) assert.strictEqual( providers[0].multiaddr.toString(), - '/ip4/2.2.2.2/tcp/1234/retrieval/bitswap' + '/ip4/2.2.2.2/tcp/1234/tag/bitswap' ) - assert.deepStrictEqual(providers[0].protos, ['bitswap']) + assert.deepStrictEqual(providers[0].tags, ['bitswap']) }) - it('supports unknown retrieval protocols', () => { + it('supports unknown tag protocols', () => { const input = `?provider=${encodeURIComponent( - `${maddr.toString()}/retrieval/magic` + `${maddr.toString()}/tag/magic` )}` const providers = parseQueryString(input) assert.strictEqual(providers.length, 1) assert.strictEqual( providers[0].multiaddr.toString(), - `${maddr.toString()}/retrieval/magic` + `${maddr.toString()}/tag/magic` ) - assert.deepStrictEqual(providers[0].protos, ['magic']) + assert.deepStrictEqual(providers[0].tags, ['magic']) }) - it('ignores trailing /retrieval without proto', () => { - const input = `?provider=${encodeURIComponent( - `${maddr.toString()}/retrieval` - )}` + it('ignores trailing /tag without proto', () => { + const input = `?provider=${encodeURIComponent(`${maddr.toString()}/tag`)}` const providers = parseQueryString(input) assert.strictEqual(providers.length, 0) }) @@ -400,11 +398,11 @@ describe('parseQueryString', () => { }) it('decodes percent-encoded multiaddrs correctly', () => { - const raw = `${maddr.toString()}/retrieval/bitswap` + const raw = `${maddr.toString()}/tag/bitswap` const encoded = encodeURIComponent(raw) const providers = parseQueryString(`?provider=${encoded}`) assert.strictEqual(providers.length, 1) assert.strictEqual(providers[0].multiaddr.toString(), raw) - assert.deepStrictEqual(providers[0].protos, ['bitswap']) + assert.deepStrictEqual(providers[0].tags, ['bitswap']) }) })