Skip to content

Commit

Permalink
feat: support base cid encodings (#148)
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos committed Jul 28, 2022
1 parent 7566a3d commit 31ed705
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 59 deletions.
1 change: 1 addition & 0 deletions packages/edge-gateway/package.json
Expand Up @@ -19,6 +19,7 @@
"mock:cf-ipfs.com": "smoke -p 9083 test/mocks/cf-ipfs.com"
},
"dependencies": {
"ipfs-core-utils": "^0.15.0",
"itty-router": "^2.4.5",
"multiformats": "^9.6.4",
"nanoid": "^3.1.30",
Expand Down
2 changes: 1 addition & 1 deletion packages/edge-gateway/src/gateway.js
Expand Up @@ -99,7 +99,7 @@ export async function gatewayGet(request, env, ctx) {
export async function gatewayIpfs(request, env, ctx, options = {}) {
const startTs = Date.now()
const reqUrl = new URL(request.url)
const cid = getCidFromSubdomainUrl(reqUrl)
const cid = await getCidFromSubdomainUrl(reqUrl)
const pathname = reqUrl.pathname

// Validation layer - root CID
Expand Down
38 changes: 36 additions & 2 deletions packages/edge-gateway/src/utils/cid.js
@@ -1,3 +1,5 @@
import { Multibases } from 'ipfs-core-utils/multibases'
import { bases } from 'multiformats/basics'
import { CID } from 'multiformats/cid'

import { InvalidUrlError } from '../errors.js'
Expand All @@ -7,7 +9,7 @@ import { InvalidUrlError } from '../errors.js'
*
* @param {URL} url
*/
export function getCidFromSubdomainUrl(url) {
export async function getCidFromSubdomainUrl(url) {
// Replace "ipfs-staging" by "ipfs" if needed
const host = url.hostname.replace('ipfs-staging', 'ipfs')
const splitHost = host.split('.ipfs.')
Expand All @@ -16,11 +18,14 @@ export function getCidFromSubdomainUrl(url) {
throw new InvalidUrlError(url.hostname)
}

let cid
try {
return normalizeCid(splitHost[0])
cid = await normalizeCidV1(splitHost[0])
} catch (err) {
throw new InvalidUrlError(`invalid CID: ${splitHost[0]}: ${err.message}`)
}

return cid
}

/**
Expand All @@ -32,3 +37,32 @@ export function normalizeCid(cid) {
const c = CID.parse(cid)
return c.toV1().toString()
}

/**
* Parse CID v1 and return normalized b32 v1
*
* @param {string} cid
*/
async function normalizeCidV1(cid) {
const baseDecoder = await getMultibaseDecoder(cid)
const c = CID.parse(cid, baseDecoder)
return c.toV1().toString()
}

/**
* Get multibase to decode CID
*
* @param {string} cid
*/
async function getMultibaseDecoder(cid) {
/** @type {MultibaseCodec[]} */
const multibaseCodecs = Object.values(bases)
const basicBases = new Multibases({
bases: multibaseCodecs,
})

const multibasePrefix = cid[0]
const base = await basicBases.getBase(multibasePrefix)

return base.decoder
}
19 changes: 18 additions & 1 deletion packages/edge-gateway/test/index.spec.js
@@ -1,6 +1,9 @@
import test from 'ava'
import { createErrorHtmlContent } from '../src/errors.js'

import { base32 } from 'multiformats/bases/base32'
import { base16 } from 'multiformats/bases/base16'

import { createErrorHtmlContent } from '../src/errors.js'
import { getMiniflare } from './utils.js'

test.beforeEach((t) => {
Expand Down Expand Up @@ -44,3 +47,17 @@ test('Gets content with path', async (t) => {
)
t.is(await response.text(), 'Hello gateway.nft.storage resource!')
})

test('Gets content with other base encodings', async (t) => {
const { mf } = t.context

const cidStr = 'bafkreidyeivj7adnnac6ljvzj2e3rd5xdw3revw4da7mx2ckrstapoupoq'
const decodedB32 = base32.decode(cidStr)
const encodedB16 = base16.encode(decodedB32)

const response = await mf.dispatchFetch(
`https://${encodedB16.toString()}.ipfs.localhost:8787`
)
await response.waitUntil()
t.is(await response.text(), 'Hello nft.storage! 馃槑')
})

0 comments on commit 31ed705

Please sign in to comment.