Skip to content

Commit

Permalink
feat: support base cid encodings (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos authored Jul 28, 2022
1 parent f6e0242 commit 2e41dc5
Show file tree
Hide file tree
Showing 8 changed files with 320 additions and 86 deletions.
4 changes: 4 additions & 0 deletions packages/edge-gateway/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
},
"dependencies": {
"@web3-storage/worker-utils": "^0.3.0-dev",
"ipfs-core-utils": "^0.15.0",
"ipfs-gateway-race": "link:../ipfs-gateway-race",
"itty-router": "^2.4.5",
"multiformats": "^9.6.4",
Expand Down Expand Up @@ -52,6 +53,9 @@
"typescript": "4.7.3",
"toml": "^3.0.0"
},
"peerDependencies": {
"undici": "^5.8.0"
},
"standard": {
"ignore": [
"dist"
Expand Down
2 changes: 1 addition & 1 deletion packages/edge-gateway/src/bindings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface EnvTransformed {
IPNS_GATEWAY_HOSTNAME: string
ipfsGateways: Array<string>
sentry?: Toucan
log?: Logging
log: Logging
gwRacer: IpfsGatewayRacer
}

Expand Down
4 changes: 2 additions & 2 deletions packages/edge-gateway/src/env.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* global BRANCH, VERSION, COMMITHASH, SENTRY_RELEASE */
import Toucan from 'toucan-js'

// @ts-ignore needs to be shipped for types
import { Logging } from '@web3-storage/worker-utils/loki'
import { createGatewayRacer } from 'ipfs-gateway-race'

Expand Down Expand Up @@ -35,9 +34,10 @@ export function envAll(request, env, ctx) {
})

env.log = new Logging(request, ctx, {
// @ts-ignore TODO: url should be optional together with token
url: env.LOKI_URL,
token: env.LOKI_TOKEN,
debug: env.DEBUG,
debug: Boolean(env.DEBUG),
version: env.VERSION,
commit: env.COMMITHASH,
branch: env.BRANCH,
Expand Down
2 changes: 1 addition & 1 deletion packages/edge-gateway/src/gateway.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export async function gatewayGet(request, env, ctx) {
}

const reqUrl = new URL(request.url)
const cid = getCidFromSubdomainUrl(reqUrl)
const cid = await getCidFromSubdomainUrl(reqUrl)
const pathname = reqUrl.pathname

// Validation layer - root CID validation
Expand Down
2 changes: 1 addition & 1 deletion packages/edge-gateway/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { errorHandler } from './error-handler.js'
import { envAll } from './env.js'

// https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent
/** @typedef {{ waitUntil(p: Promise<any>): void }} Ctx */
/** @typedef {ExecutionContext} Ctx */

const router = Router()

Expand Down
31 changes: 27 additions & 4 deletions packages/edge-gateway/src/utils/cid.js
Original file line number Diff line number Diff line change
@@ -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,19 +18,40 @@ export function getCidFromSubdomainUrl (url) {
throw new InvalidUrlError(url.hostname)
}

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

return cid
}

/**
* Parse CID and return normalized b32 v1.
*
* @param {string} cid
*/
export function normalizeCid (cid) {
const c = CID.parse(cid)
export async function normalizeCid(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) {
const multibaseCodecs = Object.values(bases)
const basicBases = new Multibases({
bases: multibaseCodecs,
})

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

return base.decoder
}
30 changes: 24 additions & 6 deletions packages/edge-gateway/test/index.spec.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { base32 } from 'multiformats/bases/base32'
import { base16 } from 'multiformats/bases/base16'

import { test, getMiniflare } from './utils/setup.js'
import { addFixtures } from './utils/fixtures.js'
import { GenericContainer, Wait } from 'testcontainers'
Expand All @@ -6,11 +9,12 @@ import { createErrorHtmlContent } from '../src/errors.js'

test.before(async (t) => {
const container = await new GenericContainer('ipfs/go-ipfs:v0.13.0')
.withExposedPorts({
container: 8080,
host: 9081
},
5001
.withExposedPorts(
{
container: 8080,
host: 9081,
},
5001
)
.withWaitStrategy(Wait.forLogMessage('Daemon is ready'))
.start()
Expand All @@ -20,7 +24,7 @@ test.before(async (t) => {

t.context = {
container,
mf: getMiniflare()
mf: getMiniflare(),
}
})

Expand Down Expand Up @@ -62,3 +66,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 = 'bafkreihl44bu5rqxctfvl3ahcln7gnjgmjqi7v5wfwojqwriqnq7wo4n7u'
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 dot.storage! 😎')
})
Loading

0 comments on commit 2e41dc5

Please sign in to comment.