Skip to content

Commit

Permalink
feat: add dir-index-html plugin and test
Browse files Browse the repository at this point in the history
  • Loading branch information
SgtPooki committed Feb 4, 2025
1 parent 7306b3a commit ce2b33f
Show file tree
Hide file tree
Showing 4 changed files with 908 additions and 4 deletions.
22 changes: 18 additions & 4 deletions packages/verified-fetch/src/plugins/plugin-handle-dag-pb.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { unixfs } from '@helia/unixfs'
import { code as dagPbCode } from '@ipld/dag-pb'
import { exporter } from 'ipfs-unixfs-exporter'
import { CustomProgressEvent } from 'progress-events'
Expand Down Expand Up @@ -44,9 +45,9 @@ export class DagPbPlugin extends BasePlugin {
return null
}

async handle (context: PluginContext): Promise<Response> {
async handle (context: PluginContext): Promise<Response | null> {
const { cid, options, withServerTiming = false, pathDetails } = context
const { handleServerTiming, contentTypeParser, helia } = this.pluginOptions
const { handleServerTiming, contentTypeParser, helia, getBlockstore } = this.pluginOptions
const log = this.log
let resource = context.resource
let path = context.path
Expand Down Expand Up @@ -94,9 +95,22 @@ export class DagPbPlugin extends BasePlugin {
path = rootFilePath
resolvedCID = entry.cid
} catch (err: any) {
this.log.error('error loading path %c/%s', dirCid, rootFilePath, err)
options?.signal?.throwIfAborted()
log('error loading path %c/%s', dirCid, rootFilePath, err)
return notSupportedResponse('Unable to find index.html for directory at given path. Support for directories with implicit root is not implemented')
context.isDirectory = true
context.directoryEntries = []
this.log.trace('attempting to get directory entries because index.html was not found')
const fs = unixfs({ ...helia, blockstore: getBlockstore(context.cid, context.resource, options?.session ?? true, options) })
try {
for await (const dirItem of fs.ls(dirCid, { signal: options?.signal, onProgress: options?.onProgress })) {
context.directoryEntries.push(dirItem)
}
// dir-index-html plugin or dir-index-json (future idea?) plugin should handle this
return null
} catch (e) {
log.error('error listing directory %c', dirCid, e)
return notSupportedResponse('Unable to get directory contents')
}

Check warning on line 113 in packages/verified-fetch/src/plugins/plugin-handle-dag-pb.ts

View check run for this annotation

Codecov / codecov/patch

packages/verified-fetch/src/plugins/plugin-handle-dag-pb.ts#L111-L113

Added lines #L111 - L113 were not covered by tests
} finally {
options?.onProgress?.(new CustomProgressEvent<CIDDetail>('verified-fetch:request:end', { cid: dirCid, path: rootFilePath }))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { code as dagPbCode } from '@ipld/dag-pb'
import { dirIndexHtml } from '../utils/dir-index-html.js'
import { okResponse } from '../utils/responses.js'
import { BasePlugin } from './plugin-base.js'
import type { PluginContext, VerifiedFetchPluginFactory } from './types.js'

export class DirIndexHtmlPlugin extends BasePlugin {
readonly codes = [dagPbCode]
canHandle (context: PluginContext): boolean {
const { cid, accept, pathDetails, directoryEntries } = context
this.log('checking if we can handle %c with accept %s', cid, accept)
if (pathDetails == null) {
return false
}
if (pathDetails.terminalElement?.type !== 'directory') {
return false

Check warning on line 16 in packages/verified-fetch/src/plugins/plugin-handle-dir-index-html.ts

View check run for this annotation

Codecov / codecov/patch

packages/verified-fetch/src/plugins/plugin-handle-dir-index-html.ts#L16

Added line #L16 was not covered by tests
}

if (directoryEntries?.length === 0) {
return false

Check warning on line 20 in packages/verified-fetch/src/plugins/plugin-handle-dir-index-html.ts

View check run for this annotation

Codecov / codecov/patch

packages/verified-fetch/src/plugins/plugin-handle-dir-index-html.ts#L20

Added line #L20 was not covered by tests
}

return cid.code === dagPbCode
}

async handle (context: PluginContext): Promise<Response> {
const { resource, pathDetails, directoryEntries } = context
// const { getBlockstore } = this.pluginOptions

if (pathDetails?.terminalElement == null) {
throw new TypeError('Path details are required')
}

Check warning on line 32 in packages/verified-fetch/src/plugins/plugin-handle-dir-index-html.ts

View check run for this annotation

Codecov / codecov/patch

packages/verified-fetch/src/plugins/plugin-handle-dir-index-html.ts#L31-L32

Added lines #L31 - L32 were not covered by tests
if (directoryEntries == null || directoryEntries?.length === 0) {
throw new TypeError('Directory entries are required')
}

Check warning on line 35 in packages/verified-fetch/src/plugins/plugin-handle-dir-index-html.ts

View check run for this annotation

Codecov / codecov/patch

packages/verified-fetch/src/plugins/plugin-handle-dir-index-html.ts#L34-L35

Added lines #L34 - L35 were not covered by tests
const terminalElement = pathDetails.terminalElement

const gatewayURL = resource
const htmlResponse = dirIndexHtml(terminalElement, directoryEntries, { gatewayURL, log: this.log })
const response = okResponse(resource, htmlResponse)
response.headers.set('content-type', 'text/html')
return response
}
}

export const dirIndexHtmlPluginFactory: VerifiedFetchPluginFactory = (opts) => new DirIndexHtmlPlugin(opts)
Loading

0 comments on commit ce2b33f

Please sign in to comment.