@helia/verified-fetch
Version:
A fetch-like API for obtaining verified & trustless IPFS content on the web
56 lines (46 loc) • 2.25 kB
text/typescript
import { code as dagCborCode } from '@ipld/dag-cbor'
import { code as dagPbCode } from '@ipld/dag-pb'
import { handlePathWalking } from '../utils/walk-path.js'
import { BasePlugin } from './plugin-base.js'
import type { PluginContext } from './types.js'
/**
* This plugin should almost always run first because it's going to handle path walking if needed, and will only say it can handle
* the request if path walking is possible (path is not empty, terminalCid is unknown, and the path has not been walked yet).
*
* Once this plugin has run, the PluginContext will be updated and then this plugin will return false for canHandle, so it won't run again.
*/
export class DagWalkPlugin extends BasePlugin {
readonly id = 'dag-walk-plugin'
/**
* Return false if the path has already been walked, otherwise return true if the CID is encoded with a codec that supports pathing.
*/
canHandle (context: PluginContext): boolean {
this.log('checking if we can handle %c with accept %s', context.cid, context.accept)
const { pathDetails, cid } = context
if (pathDetails != null) {
// path has already been walked
return false
}
return (cid.code === dagPbCode || cid.code === dagCborCode)
}
async handle (context: PluginContext): Promise<Response | null> {
const { cid, resource, options, withServerTiming = false } = context
const { getBlockstore, handleServerTiming } = this.pluginOptions
const blockstore = getBlockstore(cid, resource, options?.session ?? true, options)
// TODO: migrate handlePathWalking into this plugin
const pathDetails = await handleServerTiming('path-walking', '', async () => handlePathWalking({ ...context, blockstore, log: this.log }), withServerTiming)
if (pathDetails instanceof Response) {
this.log.trace('path walking failed')
if (pathDetails.status === 404) {
// invalid or incorrect path.. we walked the path but nothing is there
// send the 404 response
return pathDetails
}
// some other error walking the path (codec doesn't support pathing, etc..), let the next plugin try to handle it
return null
}
context.modified++
context.pathDetails = pathDetails
return null
}
}