@helia/verified-fetch 0.0.0-75d0a5b → 0.0.0-7c07e11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +205 -6
- package/dist/index.min.js +4 -4
- package/dist/src/index.d.ts +186 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +186 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/types.d.ts +2 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils/dag-cbor-to-safe-json.d.ts +7 -0
- package/dist/src/utils/dag-cbor-to-safe-json.d.ts.map +1 -0
- package/dist/src/utils/dag-cbor-to-safe-json.js +37 -0
- package/dist/src/utils/dag-cbor-to-safe-json.js.map +1 -0
- package/dist/src/utils/get-e-tag.d.ts +28 -0
- package/dist/src/utils/get-e-tag.d.ts.map +1 -0
- package/dist/src/utils/get-e-tag.js +18 -0
- package/dist/src/utils/get-e-tag.js.map +1 -0
- package/dist/src/utils/parse-url-string.d.ts +5 -1
- package/dist/src/utils/parse-url-string.d.ts.map +1 -1
- package/dist/src/utils/parse-url-string.js.map +1 -1
- package/dist/src/verified-fetch.d.ts +1 -11
- package/dist/src/verified-fetch.d.ts.map +1 -1
- package/dist/src/verified-fetch.js +25 -38
- package/dist/src/verified-fetch.js.map +1 -1
- package/package.json +18 -16
- package/src/index.ts +186 -4
- package/src/types.ts +1 -0
- package/src/utils/dag-cbor-to-safe-json.ts +44 -0
- package/src/utils/get-e-tag.ts +36 -0
- package/src/utils/parse-url-string.ts +6 -1
- package/src/verified-fetch.ts +31 -44
package/src/verified-fetch.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { dagCbor as heliaDagCbor, type DAGCBOR } from '@helia/dag-cbor'
|
|
2
|
-
import { dagJson as heliaDagJson, type DAGJSON } from '@helia/dag-json'
|
|
3
1
|
import { ipns as heliaIpns, type IPNS } from '@helia/ipns'
|
|
4
2
|
import { dnsJsonOverHttps } from '@helia/ipns/dns-resolvers'
|
|
5
|
-
import { json as heliaJson, type JSON } from '@helia/json'
|
|
6
3
|
import { unixfs as heliaUnixFs, type UnixFS as HeliaUnixFs, type UnixFSStats } from '@helia/unixfs'
|
|
7
4
|
import { code as dagCborCode } from '@ipld/dag-cbor'
|
|
8
5
|
import { code as dagJsonCode } from '@ipld/dag-json'
|
|
9
6
|
import { code as dagPbCode } from '@ipld/dag-pb'
|
|
10
7
|
import { code as jsonCode } from 'multiformats/codecs/json'
|
|
11
|
-
import {
|
|
8
|
+
import { code as rawCode } from 'multiformats/codecs/raw'
|
|
12
9
|
import { identity } from 'multiformats/hashes/identity'
|
|
13
10
|
import { CustomProgressEvent } from 'progress-events'
|
|
11
|
+
import { dagCborToSafeJSON } from './utils/dag-cbor-to-safe-json.js'
|
|
12
|
+
import { getETag } from './utils/get-e-tag.js'
|
|
14
13
|
import { getStreamFromAsyncIterable } from './utils/get-stream-from-async-iterable.js'
|
|
15
14
|
import { parseResource } from './utils/parse-resource.js'
|
|
16
15
|
import { walkPath, type PathWalkerFn } from './utils/walk-path.js'
|
|
17
16
|
import type { CIDDetail, ContentTypeParser, Resource, VerifiedFetchInit as VerifiedFetchOptions } from './index.js'
|
|
17
|
+
import type { RequestFormatShorthand } from './types.js'
|
|
18
18
|
import type { Helia } from '@helia/interface'
|
|
19
19
|
import type { AbortOptions, Logger } from '@libp2p/interface'
|
|
20
20
|
import type { UnixFSEntry } from 'ipfs-unixfs-exporter'
|
|
@@ -24,9 +24,6 @@ interface VerifiedFetchComponents {
|
|
|
24
24
|
helia: Helia
|
|
25
25
|
ipns?: IPNS
|
|
26
26
|
unixfs?: HeliaUnixFs
|
|
27
|
-
dagJson?: DAGJSON
|
|
28
|
-
json?: JSON
|
|
29
|
-
dagCbor?: DAGCBOR
|
|
30
27
|
pathWalker?: PathWalkerFn
|
|
31
28
|
}
|
|
32
29
|
|
|
@@ -81,14 +78,11 @@ export class VerifiedFetch {
|
|
|
81
78
|
private readonly helia: Helia
|
|
82
79
|
private readonly ipns: IPNS
|
|
83
80
|
private readonly unixfs: HeliaUnixFs
|
|
84
|
-
private readonly dagJson: DAGJSON
|
|
85
|
-
private readonly dagCbor: DAGCBOR
|
|
86
|
-
private readonly json: JSON
|
|
87
81
|
private readonly pathWalker: PathWalkerFn
|
|
88
82
|
private readonly log: Logger
|
|
89
83
|
private readonly contentTypeParser: ContentTypeParser | undefined
|
|
90
84
|
|
|
91
|
-
constructor ({ helia, ipns, unixfs,
|
|
85
|
+
constructor ({ helia, ipns, unixfs, pathWalker }: VerifiedFetchComponents, init?: VerifiedFetchInit) {
|
|
92
86
|
this.helia = helia
|
|
93
87
|
this.log = helia.logger.forComponent('helia:verified-fetch')
|
|
94
88
|
this.ipns = ipns ?? heliaIpns(helia, {
|
|
@@ -98,9 +92,6 @@ export class VerifiedFetch {
|
|
|
98
92
|
]
|
|
99
93
|
})
|
|
100
94
|
this.unixfs = unixfs ?? heliaUnixFs(helia)
|
|
101
|
-
this.dagJson = dagJson ?? heliaDagJson(helia)
|
|
102
|
-
this.json = json ?? heliaJson(helia)
|
|
103
|
-
this.dagCbor = dagCbor ?? heliaDagCbor(helia)
|
|
104
95
|
this.pathWalker = pathWalker ?? walkPath
|
|
105
96
|
this.contentTypeParser = init?.contentTypeParser
|
|
106
97
|
this.log.trace('created VerifiedFetch instance')
|
|
@@ -120,42 +111,36 @@ export class VerifiedFetch {
|
|
|
120
111
|
return response
|
|
121
112
|
}
|
|
122
113
|
|
|
123
|
-
private async handleDagJson ({ cid, path, options }: FetchHandlerFunctionArg): Promise<Response> {
|
|
124
|
-
this.log.trace('fetching %c/%s', cid, path)
|
|
125
|
-
options?.onProgress?.(new CustomProgressEvent<CIDDetail>('verified-fetch:request:start', { cid, path }))
|
|
126
|
-
const result = await this.dagJson.get(cid, {
|
|
127
|
-
signal: options?.signal,
|
|
128
|
-
onProgress: options?.onProgress
|
|
129
|
-
})
|
|
130
|
-
options?.onProgress?.(new CustomProgressEvent<CIDDetail>('verified-fetch:request:end', { cid, path }))
|
|
131
|
-
const response = okResponse(JSON.stringify(result))
|
|
132
|
-
response.headers.set('content-type', 'application/json')
|
|
133
|
-
return response
|
|
134
|
-
}
|
|
135
|
-
|
|
136
114
|
private async handleJson ({ cid, path, options }: FetchHandlerFunctionArg): Promise<Response> {
|
|
137
115
|
this.log.trace('fetching %c/%s', cid, path)
|
|
138
116
|
options?.onProgress?.(new CustomProgressEvent<CIDDetail>('verified-fetch:request:start', { cid, path }))
|
|
139
|
-
const result
|
|
117
|
+
const result = await this.helia.blockstore.get(cid, {
|
|
140
118
|
signal: options?.signal,
|
|
141
119
|
onProgress: options?.onProgress
|
|
142
120
|
})
|
|
143
|
-
|
|
144
|
-
const response = okResponse(JSON.stringify(result))
|
|
121
|
+
const response = okResponse(result)
|
|
145
122
|
response.headers.set('content-type', 'application/json')
|
|
123
|
+
options?.onProgress?.(new CustomProgressEvent<CIDDetail>('verified-fetch:request:end', { cid, path }))
|
|
146
124
|
return response
|
|
147
125
|
}
|
|
148
126
|
|
|
149
127
|
private async handleDagCbor ({ cid, path, options }: FetchHandlerFunctionArg): Promise<Response> {
|
|
150
128
|
this.log.trace('fetching %c/%s', cid, path)
|
|
151
129
|
options?.onProgress?.(new CustomProgressEvent<CIDDetail>('verified-fetch:request:start', { cid, path }))
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
130
|
+
// return body as binary
|
|
131
|
+
const block = await this.helia.blockstore.get(cid)
|
|
132
|
+
let body: string | Uint8Array
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
body = dagCborToSafeJSON(block)
|
|
136
|
+
} catch (err) {
|
|
137
|
+
this.log('could not decode DAG-CBOR as JSON-safe, falling back to `application/octet-stream`', err)
|
|
138
|
+
body = block
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const response = okResponse(body)
|
|
142
|
+
response.headers.set('content-type', body instanceof Uint8Array ? 'application/octet-stream' : 'application/json')
|
|
156
143
|
options?.onProgress?.(new CustomProgressEvent<CIDDetail>('verified-fetch:request:end', { cid, path }))
|
|
157
|
-
const response = okResponse(JSON.stringify(result))
|
|
158
|
-
await this.setContentType(result, path, response)
|
|
159
144
|
return response
|
|
160
145
|
}
|
|
161
146
|
|
|
@@ -192,7 +177,6 @@ export class VerifiedFetch {
|
|
|
192
177
|
signal: options?.signal,
|
|
193
178
|
onProgress: options?.onProgress
|
|
194
179
|
})
|
|
195
|
-
options?.onProgress?.(new CustomProgressEvent<CIDDetail>('verified-fetch:request:end', { cid: resolvedCID, path: '' }))
|
|
196
180
|
this.log('got async iterator for %c/%s', cid, path)
|
|
197
181
|
|
|
198
182
|
const { stream, firstChunk } = await getStreamFromAsyncIterable(asyncIter, path ?? '', this.helia.logger, {
|
|
@@ -201,6 +185,8 @@ export class VerifiedFetch {
|
|
|
201
185
|
const response = okResponse(stream)
|
|
202
186
|
await this.setContentType(firstChunk, path, response)
|
|
203
187
|
|
|
188
|
+
options?.onProgress?.(new CustomProgressEvent<CIDDetail>('verified-fetch:request:end', { cid: resolvedCID, path: '' }))
|
|
189
|
+
|
|
204
190
|
return response
|
|
205
191
|
}
|
|
206
192
|
|
|
@@ -208,9 +194,10 @@ export class VerifiedFetch {
|
|
|
208
194
|
this.log.trace('fetching %c/%s', cid, path)
|
|
209
195
|
options?.onProgress?.(new CustomProgressEvent<CIDDetail>('verified-fetch:request:start', { cid, path }))
|
|
210
196
|
const result = await this.helia.blockstore.get(cid)
|
|
211
|
-
|
|
212
|
-
const response = okResponse(decode(result))
|
|
197
|
+
const response = okResponse(result)
|
|
213
198
|
await this.setContentType(result, path, response)
|
|
199
|
+
|
|
200
|
+
options?.onProgress?.(new CustomProgressEvent<CIDDetail>('verified-fetch:request:end', { cid, path }))
|
|
214
201
|
return response
|
|
215
202
|
}
|
|
216
203
|
|
|
@@ -246,8 +233,8 @@ export class VerifiedFetch {
|
|
|
246
233
|
* @see https://specs.ipfs.tech/http-gateways/path-gateway/#format-request-query-parameter
|
|
247
234
|
* @default 'raw'
|
|
248
235
|
*/
|
|
249
|
-
private getFormat ({ headerFormat, queryFormat }: { headerFormat: string | null, queryFormat:
|
|
250
|
-
const formatMap: Record<string,
|
|
236
|
+
private getFormat ({ headerFormat, queryFormat }: { headerFormat: string | null, queryFormat: RequestFormatShorthand | null }): RequestFormatShorthand | null {
|
|
237
|
+
const formatMap: Record<string, RequestFormatShorthand> = {
|
|
251
238
|
'vnd.ipld.raw': 'raw',
|
|
252
239
|
'vnd.ipld.car': 'car',
|
|
253
240
|
'application/x-tar': 'tar',
|
|
@@ -287,8 +274,8 @@ export class VerifiedFetch {
|
|
|
287
274
|
}
|
|
288
275
|
|
|
289
276
|
private readonly codecHandlers: Record<number, FetchHandlerFunction> = {
|
|
290
|
-
[dagJsonCode]: this.handleDagJson,
|
|
291
277
|
[dagPbCode]: this.handleDagPb,
|
|
278
|
+
[dagJsonCode]: this.handleJson,
|
|
292
279
|
[jsonCode]: this.handleJson,
|
|
293
280
|
[dagCborCode]: this.handleDagCbor,
|
|
294
281
|
[rawCode]: this.handleRaw,
|
|
@@ -338,8 +325,8 @@ export class VerifiedFetch {
|
|
|
338
325
|
}
|
|
339
326
|
}
|
|
340
327
|
|
|
341
|
-
response.headers.set('etag', cid
|
|
342
|
-
response.headers.set('cache-
|
|
328
|
+
response.headers.set('etag', getETag({ cid, reqFormat: format ?? undefined, weak: false }))
|
|
329
|
+
response.headers.set('cache-control', 'public, max-age=29030400, immutable')
|
|
343
330
|
response.headers.set('X-Ipfs-Path', resource.toString()) // https://specs.ipfs.tech/http-gateways/path-gateway/#x-ipfs-path-response-header
|
|
344
331
|
|
|
345
332
|
if (ipfsRoots != null) {
|