@helia/verified-fetch 3.2.3 → 4.0.0
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 +5 -5
- package/dist/index.min.js +81 -71
- package/dist/index.min.js.map +4 -4
- package/dist/src/constants.d.ts +2 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +2 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/index.d.ts +57 -13
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -6
- package/dist/src/index.js.map +1 -1
- package/dist/src/plugins/plugin-handle-car.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-car.js +37 -27
- package/dist/src/plugins/plugin-handle-car.js.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.d.ts +1 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.js +1 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.js.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-cbor.js +5 -5
- package/dist/src/plugins/plugin-handle-dag-cbor.js.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-pb.js +12 -12
- package/dist/src/plugins/plugin-handle-dag-pb.js.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-walk.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-walk.js +5 -4
- package/dist/src/plugins/plugin-handle-dag-walk.js.map +1 -1
- package/dist/src/plugins/plugin-handle-ipns-record.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-ipns-record.js +13 -19
- package/dist/src/plugins/plugin-handle-ipns-record.js.map +1 -1
- package/dist/src/plugins/plugin-handle-json.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-json.js +5 -4
- package/dist/src/plugins/plugin-handle-json.js.map +1 -1
- package/dist/src/plugins/plugin-handle-raw.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-raw.js +18 -5
- package/dist/src/plugins/plugin-handle-raw.js.map +1 -1
- package/dist/src/plugins/plugin-handle-tar.js +1 -1
- package/dist/src/plugins/plugin-handle-tar.js.map +1 -1
- package/dist/src/plugins/types.d.ts +10 -8
- package/dist/src/plugins/types.d.ts.map +1 -1
- package/dist/src/url-resolver.d.ts +21 -0
- package/dist/src/url-resolver.d.ts.map +1 -0
- package/dist/src/url-resolver.js +118 -0
- package/dist/src/url-resolver.js.map +1 -0
- package/dist/src/utils/byte-range-context.d.ts +1 -1
- package/dist/src/utils/get-content-type.d.ts +3 -3
- package/dist/src/utils/get-content-type.d.ts.map +1 -1
- package/dist/src/utils/get-content-type.js +1 -1
- package/dist/src/utils/get-content-type.js.map +1 -1
- package/dist/src/utils/get-e-tag.d.ts +1 -1
- package/dist/src/utils/get-offset-and-length.d.ts +6 -0
- package/dist/src/utils/get-offset-and-length.d.ts.map +1 -0
- package/dist/src/utils/get-offset-and-length.js +46 -0
- package/dist/src/utils/get-offset-and-length.js.map +1 -0
- package/dist/src/utils/get-resolved-accept-header.d.ts +2 -2
- package/dist/src/utils/get-resolved-accept-header.d.ts.map +1 -1
- package/dist/src/utils/handle-redirects.d.ts.map +1 -1
- package/dist/src/utils/handle-redirects.js +3 -3
- package/dist/src/utils/handle-redirects.js.map +1 -1
- package/dist/src/utils/ipfs-path-to-string.d.ts +6 -0
- package/dist/src/utils/ipfs-path-to-string.d.ts.map +1 -0
- package/dist/src/utils/ipfs-path-to-string.js +10 -0
- package/dist/src/utils/ipfs-path-to-string.js.map +1 -0
- package/dist/src/utils/is-accept-explicit.d.ts +6 -4
- package/dist/src/utils/is-accept-explicit.d.ts.map +1 -1
- package/dist/src/utils/is-accept-explicit.js +7 -4
- package/dist/src/utils/is-accept-explicit.js.map +1 -1
- package/dist/src/utils/parse-url-string.d.ts +1 -55
- package/dist/src/utils/parse-url-string.d.ts.map +1 -1
- package/dist/src/utils/parse-url-string.js +16 -217
- package/dist/src/utils/parse-url-string.js.map +1 -1
- package/dist/src/utils/response-headers.d.ts +1 -1
- package/dist/src/utils/response-headers.d.ts.map +1 -1
- package/dist/src/utils/responses.d.ts +1 -1
- package/dist/src/utils/select-output-type.d.ts +6 -2
- package/dist/src/utils/select-output-type.d.ts.map +1 -1
- package/dist/src/utils/select-output-type.js +28 -37
- package/dist/src/utils/select-output-type.js.map +1 -1
- package/dist/src/utils/server-timing.d.ts +5 -11
- package/dist/src/utils/server-timing.d.ts.map +1 -1
- package/dist/src/utils/server-timing.js +17 -15
- package/dist/src/utils/server-timing.js.map +1 -1
- package/dist/src/utils/walk-path.js +1 -1
- package/dist/src/utils/walk-path.js.map +1 -1
- package/dist/src/verified-fetch.d.ts +3 -10
- package/dist/src/verified-fetch.d.ts.map +1 -1
- package/dist/src/verified-fetch.js +68 -57
- package/dist/src/verified-fetch.js.map +1 -1
- package/dist/typedoc-urls.json +13 -2
- package/package.json +35 -36
- package/src/constants.ts +1 -0
- package/src/index.ts +73 -22
- package/src/plugins/plugin-handle-car.ts +54 -30
- package/src/plugins/plugin-handle-dag-cbor-html-preview.ts +2 -2
- package/src/plugins/plugin-handle-dag-cbor.ts +5 -5
- package/src/plugins/plugin-handle-dag-pb.ts +12 -12
- package/src/plugins/plugin-handle-dag-walk.ts +5 -4
- package/src/plugins/plugin-handle-ipns-record.ts +16 -19
- package/src/plugins/plugin-handle-json.ts +5 -4
- package/src/plugins/plugin-handle-raw.ts +21 -6
- package/src/plugins/plugin-handle-tar.ts +1 -1
- package/src/plugins/types.ts +12 -8
- package/src/url-resolver.ts +159 -0
- package/src/utils/byte-range-context.ts +1 -1
- package/src/utils/get-content-type.ts +5 -4
- package/src/utils/get-e-tag.ts +1 -1
- package/src/utils/get-offset-and-length.ts +54 -0
- package/src/utils/get-resolved-accept-header.ts +2 -2
- package/src/utils/handle-redirects.ts +10 -3
- package/src/utils/ipfs-path-to-string.ts +9 -0
- package/src/utils/is-accept-explicit.ts +14 -7
- package/src/utils/parse-url-string.ts +20 -286
- package/src/utils/response-headers.ts +1 -1
- package/src/utils/responses.ts +1 -1
- package/src/utils/select-output-type.ts +38 -44
- package/src/utils/server-timing.ts +17 -30
- package/src/utils/walk-path.ts +1 -1
- package/src/verified-fetch.ts +78 -69
- package/dist/src/types.d.ts +0 -16
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js +0 -2
- package/dist/src/types.js.map +0 -1
- package/dist/src/utils/parse-resource.d.ts +0 -18
- package/dist/src/utils/parse-resource.d.ts.map +0 -1
- package/dist/src/utils/parse-resource.js +0 -27
- package/dist/src/utils/parse-resource.js.map +0 -1
- package/src/types.ts +0 -17
- package/src/utils/parse-resource.ts +0 -42
package/dist/typedoc-urls.json
CHANGED
|
@@ -11,23 +11,34 @@
|
|
|
11
11
|
"CIDDetailError": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.CIDDetailError.html",
|
|
12
12
|
".:CIDDetailError": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.CIDDetailError.html",
|
|
13
13
|
"ContentTypeParser": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.ContentTypeParser.html",
|
|
14
|
+
".:ContentTypeParser": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.ContentTypeParser.html",
|
|
14
15
|
"CreateVerifiedFetchInit": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.CreateVerifiedFetchInit.html",
|
|
15
16
|
".:CreateVerifiedFetchInit": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.CreateVerifiedFetchInit.html",
|
|
16
17
|
"CreateVerifiedFetchOptions": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.CreateVerifiedFetchOptions.html",
|
|
17
18
|
".:CreateVerifiedFetchOptions": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.CreateVerifiedFetchOptions.html",
|
|
18
19
|
"PluginContext": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.PluginContext.html",
|
|
19
20
|
"PluginOptions": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.PluginOptions.html",
|
|
21
|
+
"ResolveURLOptions": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.ResolveURLOptions.html",
|
|
22
|
+
".:ResolveURLOptions": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.ResolveURLOptions.html",
|
|
23
|
+
"ResolveURLResult": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.ResolveURLResult.html",
|
|
24
|
+
".:ResolveURLResult": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.ResolveURLResult.html",
|
|
20
25
|
"ResourceDetail": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.ResourceDetail.html",
|
|
21
26
|
".:ResourceDetail": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.ResourceDetail.html",
|
|
27
|
+
"UrlQuery": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.UrlQuery.html",
|
|
28
|
+
".:UrlQuery": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.UrlQuery.html",
|
|
29
|
+
"URLResolver": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.URLResolver.html",
|
|
30
|
+
".:URLResolver": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.URLResolver.html",
|
|
22
31
|
"VerifiedFetch": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.VerifiedFetch.html",
|
|
23
32
|
".:VerifiedFetch": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.VerifiedFetch.html",
|
|
24
33
|
"VerifiedFetchInit": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.VerifiedFetchInit.html",
|
|
25
34
|
".:VerifiedFetchInit": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.VerifiedFetchInit.html",
|
|
26
35
|
"VerifiedFetchPluginFactory": "https://ipfs.github.io/helia-verified-fetch/interfaces/index.VerifiedFetchPluginFactory.html",
|
|
27
|
-
"
|
|
28
|
-
".:
|
|
36
|
+
"RequestFormatShorthand": "https://ipfs.github.io/helia-verified-fetch/types/index.RequestFormatShorthand.html",
|
|
37
|
+
".:RequestFormatShorthand": "https://ipfs.github.io/helia-verified-fetch/types/index.RequestFormatShorthand.html",
|
|
29
38
|
"Resource": "https://ipfs.github.io/helia-verified-fetch/types/index.Resource.html",
|
|
30
39
|
".:Resource": "https://ipfs.github.io/helia-verified-fetch/types/index.Resource.html",
|
|
40
|
+
"SupportedBodyTypes": "https://ipfs.github.io/helia-verified-fetch/types/index.SupportedBodyTypes.html",
|
|
41
|
+
".:SupportedBodyTypes": "https://ipfs.github.io/helia-verified-fetch/types/index.SupportedBodyTypes.html",
|
|
31
42
|
"VerifiedFetchProgressEvents": "https://ipfs.github.io/helia-verified-fetch/types/index.VerifiedFetchProgressEvents.html",
|
|
32
43
|
".:VerifiedFetchProgressEvents": "https://ipfs.github.io/helia-verified-fetch/types/index.VerifiedFetchProgressEvents.html",
|
|
33
44
|
"dagCborHtmlPreviewPluginFactory": "https://ipfs.github.io/helia-verified-fetch/variables/index.dagCborHtmlPreviewPluginFactory.html",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helia/verified-fetch",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "A fetch-like API for obtaining verified & trustless IPFS content on the web",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"homepage": "https://github.com/ipfs/helia-verified-fetch/tree/main/packages/verified-fetch#readme",
|
|
@@ -164,61 +164,60 @@
|
|
|
164
164
|
"release": "aegir release"
|
|
165
165
|
},
|
|
166
166
|
"dependencies": {
|
|
167
|
-
"@helia/block-brokers": "^
|
|
168
|
-
"@helia/car": "^
|
|
169
|
-
"@helia/delegated-routing-v1-http-api-client": "^
|
|
170
|
-
"@helia/
|
|
171
|
-
"@helia/
|
|
172
|
-
"@helia/
|
|
173
|
-
"@helia/
|
|
174
|
-
"@
|
|
167
|
+
"@helia/block-brokers": "^5.0.4",
|
|
168
|
+
"@helia/car": "^5.2.0",
|
|
169
|
+
"@helia/delegated-routing-v1-http-api-client": "^5.0.0",
|
|
170
|
+
"@helia/dnslink": "^1.0.1",
|
|
171
|
+
"@helia/interface": "^6.0.0",
|
|
172
|
+
"@helia/ipns": "^9.0.0",
|
|
173
|
+
"@helia/routers": "^4.0.0",
|
|
174
|
+
"@helia/unixfs": "^6.0.0",
|
|
175
175
|
"@ipld/dag-cbor": "^9.2.3",
|
|
176
176
|
"@ipld/dag-json": "^10.2.4",
|
|
177
177
|
"@ipld/dag-pb": "^4.1.5",
|
|
178
|
-
"@libp2p/interface": "^
|
|
179
|
-
"@libp2p/kad-dht": "^
|
|
180
|
-
"@libp2p/logger": "^
|
|
181
|
-
"@libp2p/peer-id": "^
|
|
182
|
-
"@libp2p/
|
|
183
|
-
"@libp2p/
|
|
178
|
+
"@libp2p/interface": "^3.0.0",
|
|
179
|
+
"@libp2p/kad-dht": "^16.0.0",
|
|
180
|
+
"@libp2p/logger": "^6.0.0",
|
|
181
|
+
"@libp2p/peer-id": "^6.0.0",
|
|
182
|
+
"@libp2p/utils": "^7.0.5",
|
|
183
|
+
"@libp2p/webrtc": "^6.0.0",
|
|
184
|
+
"@libp2p/websockets": "^10.0.0",
|
|
184
185
|
"@multiformats/dns": "^1.0.6",
|
|
185
186
|
"cborg": "^4.2.11",
|
|
186
|
-
"file-type": "^
|
|
187
|
-
"helia": "^
|
|
188
|
-
"interface-blockstore": "^
|
|
189
|
-
"
|
|
190
|
-
"
|
|
191
|
-
"ipns": "^10.0.2",
|
|
187
|
+
"file-type": "^21.0.0",
|
|
188
|
+
"helia": "^6.0.5",
|
|
189
|
+
"interface-blockstore": "^6.0.1",
|
|
190
|
+
"ipfs-unixfs-exporter": "^14.0.1",
|
|
191
|
+
"ipns": "^10.1.3",
|
|
192
192
|
"it-map": "^3.1.3",
|
|
193
193
|
"it-pipe": "^3.0.1",
|
|
194
194
|
"it-tar": "^6.0.5",
|
|
195
195
|
"it-to-browser-readablestream": "^2.0.11",
|
|
196
|
-
"
|
|
196
|
+
"it-to-buffer": "^4.0.9",
|
|
197
|
+
"libp2p": "^3.0.0",
|
|
197
198
|
"multiformats": "^13.3.6",
|
|
198
199
|
"progress-events": "^1.0.1",
|
|
199
|
-
"quick-lru": "^7.0.1"
|
|
200
|
-
"uint8arrays": "^5.1.0"
|
|
200
|
+
"quick-lru": "^7.0.1"
|
|
201
201
|
},
|
|
202
202
|
"devDependencies": {
|
|
203
|
-
"@helia/dag-cbor": "^
|
|
204
|
-
"@helia/dag-json": "^
|
|
205
|
-
"@helia/http": "^
|
|
206
|
-
"@helia/json": "^
|
|
203
|
+
"@helia/dag-cbor": "^5.0.0",
|
|
204
|
+
"@helia/dag-json": "^5.0.0",
|
|
205
|
+
"@helia/http": "^3.0.5",
|
|
206
|
+
"@helia/json": "^5.0.0",
|
|
207
|
+
"@ipld/car": "^5.4.2",
|
|
207
208
|
"@libp2p/crypto": "^5.1.3",
|
|
208
209
|
"@types/sinon": "^17.0.4",
|
|
209
|
-
"aegir": "^47.0.
|
|
210
|
-
"blockstore-core": "^5.0.2",
|
|
210
|
+
"aegir": "^47.0.24",
|
|
211
211
|
"browser-readablestream-to-it": "^2.0.9",
|
|
212
|
-
"
|
|
213
|
-
"helia": "^5.4.1",
|
|
214
|
-
"ipfs-unixfs-importer": "^15.4.0",
|
|
212
|
+
"ipfs-unixfs-importer": "^16.0.1",
|
|
215
213
|
"it-all": "^3.0.8",
|
|
216
214
|
"it-last": "^3.0.8",
|
|
217
|
-
"it-to-buffer": "^4.0.9",
|
|
218
215
|
"magic-bytes.js": "^1.12.1",
|
|
219
216
|
"p-defer": "^4.0.1",
|
|
220
|
-
"
|
|
221
|
-
"sinon
|
|
217
|
+
"race-signal": "^2.0.0",
|
|
218
|
+
"sinon": "^21.0.0",
|
|
219
|
+
"sinon-ts": "^2.0.0",
|
|
220
|
+
"uint8arrays": "^5.1.0"
|
|
222
221
|
},
|
|
223
222
|
"browser": {
|
|
224
223
|
"./dist/src/utils/libp2p-defaults.js": "./dist/src/utils/libp2p-defaults.browser.js"
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CODEC_IDENTITY = 0x00
|
package/src/index.ts
CHANGED
|
@@ -745,12 +745,12 @@
|
|
|
745
745
|
* canHandle(context: PluginContext): boolean {
|
|
746
746
|
* // Only handle requests if the Accept header matches your custom type
|
|
747
747
|
* // Or check context for pathDetails, custom values, etc...
|
|
748
|
-
* return context.accept === 'application/vnd.my-custom-type'
|
|
748
|
+
* return context.accept?.mimeType === 'application/vnd.my-custom-type'
|
|
749
749
|
* }
|
|
750
750
|
*
|
|
751
751
|
* async handle(context: PluginContext): Promise<Response | null> {
|
|
752
752
|
* // Perform any partial processing here, e.g., modify the context:
|
|
753
|
-
* context.customProcessed = true
|
|
753
|
+
* context.customProcessed = true
|
|
754
754
|
*
|
|
755
755
|
* // If you are ready to finalize the response:
|
|
756
756
|
* return new Response('Hello, world!', {
|
|
@@ -758,7 +758,7 @@
|
|
|
758
758
|
* headers: {
|
|
759
759
|
* 'Content-Type': 'text/plain'
|
|
760
760
|
* }
|
|
761
|
-
* })
|
|
761
|
+
* })
|
|
762
762
|
*
|
|
763
763
|
* // Or, if further processing is needed by another plugin, simply return null.
|
|
764
764
|
* }
|
|
@@ -812,13 +812,13 @@
|
|
|
812
812
|
* details: {
|
|
813
813
|
* someKey: 'Additional details here'
|
|
814
814
|
* }
|
|
815
|
-
* })
|
|
815
|
+
* })
|
|
816
816
|
* }
|
|
817
817
|
*
|
|
818
818
|
* if (recoverable === false) {
|
|
819
819
|
* throw new PluginFatalError('MY_CUSTOM_FATAL', 'A critical error occurred', {
|
|
820
820
|
* response: new Response('Something happened', { status: 500 }) // Required: supply your own error response
|
|
821
|
-
* })
|
|
821
|
+
* })
|
|
822
822
|
* }
|
|
823
823
|
*
|
|
824
824
|
* // Otherwise, continue processing...
|
|
@@ -857,10 +857,10 @@ import { createLibp2p } from 'libp2p'
|
|
|
857
857
|
import { getLibp2pConfig } from './utils/libp2p-defaults.js'
|
|
858
858
|
import { VerifiedFetch as VerifiedFetchClass } from './verified-fetch.js'
|
|
859
859
|
import type { VerifiedFetchPluginFactory } from './plugins/types.js'
|
|
860
|
-
import type {
|
|
860
|
+
import type { DNSLink, ResolveProgressEvents as ResolveDNSLinkProgressEvents } from '@helia/dnslink'
|
|
861
861
|
import type { GetBlockProgressEvents, Helia, Routing } from '@helia/interface'
|
|
862
|
-
import type {
|
|
863
|
-
import type { Libp2p, ServiceMap } from '@libp2p/interface'
|
|
862
|
+
import type { IPNSResolver } from '@helia/ipns'
|
|
863
|
+
import type { AbortOptions, Libp2p, ServiceMap } from '@libp2p/interface'
|
|
864
864
|
import type { DNSResolvers, DNS } from '@multiformats/dns'
|
|
865
865
|
import type { DNSResolver } from '@multiformats/dns/resolvers'
|
|
866
866
|
import type { HeliaInit } from 'helia'
|
|
@@ -868,6 +868,25 @@ import type { ExporterProgressEvents } from 'ipfs-unixfs-exporter'
|
|
|
868
868
|
import type { Libp2pOptions } from 'libp2p'
|
|
869
869
|
import type { CID } from 'multiformats/cid'
|
|
870
870
|
import type { ProgressEvent, ProgressOptions } from 'progress-events'
|
|
871
|
+
|
|
872
|
+
export type RequestFormatShorthand = 'raw' | 'car' | 'tar' | 'ipns-record' | 'dag-json' | 'dag-cbor' | 'json' | 'cbor'
|
|
873
|
+
|
|
874
|
+
export type SupportedBodyTypes = string | Uint8Array | ArrayBuffer | Blob | ReadableStream<Uint8Array> | null
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* A ContentTypeParser attempts to return the mime type of a given file. It
|
|
878
|
+
* receives the first chunk of the file data and the file name, if it is
|
|
879
|
+
* available. The function can be sync or async and if it returns/resolves to
|
|
880
|
+
* `undefined`, `application/octet-stream` will be used.
|
|
881
|
+
*/
|
|
882
|
+
export interface ContentTypeParser {
|
|
883
|
+
/**
|
|
884
|
+
* Attempt to determine a mime type, either via of the passed bytes or the
|
|
885
|
+
* filename if it is available.
|
|
886
|
+
*/
|
|
887
|
+
(bytes: Uint8Array, fileName?: string): Promise<string | undefined> | string | undefined
|
|
888
|
+
}
|
|
889
|
+
|
|
871
890
|
/**
|
|
872
891
|
* The types for the first argument of the `verifiedFetch` function.
|
|
873
892
|
*/
|
|
@@ -879,7 +898,7 @@ export interface ResourceDetail {
|
|
|
879
898
|
|
|
880
899
|
export interface CIDDetail {
|
|
881
900
|
cid: CID
|
|
882
|
-
path
|
|
901
|
+
path?: string
|
|
883
902
|
}
|
|
884
903
|
|
|
885
904
|
export interface CIDDetailError extends CIDDetail {
|
|
@@ -995,24 +1014,32 @@ export interface CreateVerifiedFetchOptions {
|
|
|
995
1014
|
* If you want to replace one of the default plugins, you can do so by passing a plugin with the same name.
|
|
996
1015
|
*/
|
|
997
1016
|
plugins?: VerifiedFetchPluginFactory[]
|
|
998
|
-
}
|
|
999
1017
|
|
|
1000
|
-
|
|
1018
|
+
/**
|
|
1019
|
+
* Used to resolve IPNS names
|
|
1020
|
+
*/
|
|
1021
|
+
ipnsResolver?: IPNSResolver
|
|
1001
1022
|
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1023
|
+
/**
|
|
1024
|
+
* Used to resolve DNSLink entries to IPNS names or CIDs
|
|
1025
|
+
*/
|
|
1026
|
+
dnsLink?: DNSLink
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Used to turn URLs into CIDs/paths
|
|
1030
|
+
*/
|
|
1031
|
+
urlResolver?: URLResolver
|
|
1032
|
+
}
|
|
1009
1033
|
|
|
1010
1034
|
export type VerifiedFetchProgressEvents =
|
|
1011
1035
|
ProgressEvent<'verified-fetch:request:start', CIDDetail> |
|
|
1012
1036
|
ProgressEvent<'verified-fetch:request:info', string> |
|
|
1013
|
-
ProgressEvent<'verified-fetch:request:progress:chunk'
|
|
1037
|
+
ProgressEvent<'verified-fetch:request:progress:chunk'> |
|
|
1014
1038
|
ProgressEvent<'verified-fetch:request:end', CIDDetail> |
|
|
1015
|
-
ProgressEvent<'verified-fetch:request:error', CIDDetailError>
|
|
1039
|
+
ProgressEvent<'verified-fetch:request:error', CIDDetailError> |
|
|
1040
|
+
ExporterProgressEvents |
|
|
1041
|
+
GetBlockProgressEvents |
|
|
1042
|
+
ResolveDNSLinkProgressEvents
|
|
1016
1043
|
|
|
1017
1044
|
/**
|
|
1018
1045
|
* Options for the `fetch` function returned by `createVerifiedFetch`.
|
|
@@ -1021,7 +1048,7 @@ export type VerifiedFetchProgressEvents =
|
|
|
1021
1048
|
* passed to `fetch` in browsers, plus an `onProgress` option to listen for
|
|
1022
1049
|
* progress events.
|
|
1023
1050
|
*/
|
|
1024
|
-
export interface VerifiedFetchInit extends RequestInit, ProgressOptions<
|
|
1051
|
+
export interface VerifiedFetchInit extends RequestInit, ProgressOptions<VerifiedFetchProgressEvents> {
|
|
1025
1052
|
/**
|
|
1026
1053
|
* If true, try to create a blockstore session - this can reduce overall
|
|
1027
1054
|
* network traffic by first querying for a set of peers that have the data we
|
|
@@ -1072,6 +1099,30 @@ export interface VerifiedFetchInit extends RequestInit, ProgressOptions<BubbledP
|
|
|
1072
1099
|
withServerTiming?: boolean
|
|
1073
1100
|
}
|
|
1074
1101
|
|
|
1102
|
+
export interface ResolveURLOptions extends ProgressOptions<VerifiedFetchProgressEvents>, AbortOptions {
|
|
1103
|
+
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
export interface UrlQuery extends Record<string, string | unknown> {
|
|
1107
|
+
format?: RequestFormatShorthand
|
|
1108
|
+
download?: boolean
|
|
1109
|
+
filename?: string
|
|
1110
|
+
'dag-scope'?: string
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
export interface ResolveURLResult {
|
|
1114
|
+
cid: CID
|
|
1115
|
+
protocol: string
|
|
1116
|
+
ttl: number
|
|
1117
|
+
path: string
|
|
1118
|
+
query: UrlQuery
|
|
1119
|
+
ipfsPath: string
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
export interface URLResolver {
|
|
1123
|
+
resolve (resource: Resource, options?: ResolveURLOptions): Promise<ResolveURLResult>
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1075
1126
|
/**
|
|
1076
1127
|
* Create and return a Helia node
|
|
1077
1128
|
*/
|
|
@@ -1116,7 +1167,7 @@ export async function createVerifiedFetch (init?: Helia | CreateVerifiedFetchIni
|
|
|
1116
1167
|
init.logger.forComponent('helia:verified-fetch').trace('created verified-fetch with libp2p config: %j', libp2pConfig)
|
|
1117
1168
|
}
|
|
1118
1169
|
|
|
1119
|
-
const verifiedFetchInstance = new VerifiedFetchClass(
|
|
1170
|
+
const verifiedFetchInstance = new VerifiedFetchClass(init, options)
|
|
1120
1171
|
async function verifiedFetch (resource: Resource, options?: VerifiedFetchInit): Promise<Response> {
|
|
1121
1172
|
return verifiedFetchInstance.fetch(resource, options)
|
|
1122
1173
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { BlockExporter, car, CIDPath, SubgraphExporter, UnixFSExporter } from '@helia/car'
|
|
2
|
-
import { CarWriter } from '@ipld/car'
|
|
3
2
|
import { code as dagPbCode } from '@ipld/dag-pb'
|
|
3
|
+
import { createScalableCuckooFilter } from '@libp2p/utils'
|
|
4
4
|
import toBrowserReadableStream from 'it-to-browser-readablestream'
|
|
5
|
+
import { getOffsetAndLength } from '../utils/get-offset-and-length.ts'
|
|
5
6
|
import { okRangeResponse } from '../utils/responses.js'
|
|
6
7
|
import { BasePlugin } from './plugin-base.js'
|
|
7
8
|
import type { PluginContext } from './types.js'
|
|
8
|
-
import type { ExportCarOptions } from '@helia/car'
|
|
9
|
+
import type { ExportCarOptions, UnixFSExporterOptions } from '@helia/car'
|
|
9
10
|
|
|
10
11
|
function getFilename ({ cid, ipfsPath, query }: Pick<PluginContext, 'query' | 'cid' | 'ipfsPath'>): string {
|
|
11
12
|
if (query.filename != null) {
|
|
@@ -13,7 +14,10 @@ function getFilename ({ cid, ipfsPath, query }: Pick<PluginContext, 'query' | 'c
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
// convert context.ipfsPath to a filename. replace all / with _, replace prefix protocol with empty string
|
|
16
|
-
const filename = ipfsPath
|
|
17
|
+
const filename = ipfsPath
|
|
18
|
+
.replace(/\/ipfs\//, '')
|
|
19
|
+
.replace(/\/ipns\//, '')
|
|
20
|
+
.replace(/\//g, '_')
|
|
17
21
|
|
|
18
22
|
return `${filename}.car`
|
|
19
23
|
}
|
|
@@ -22,9 +26,16 @@ function getFilename ({ cid, ipfsPath, query }: Pick<PluginContext, 'query' | 'c
|
|
|
22
26
|
type DagScope = 'all' | 'entity' | 'block'
|
|
23
27
|
function getDagScope ({ query }: Pick<PluginContext, 'query'>): DagScope | null {
|
|
24
28
|
const dagScope = query['dag-scope']
|
|
29
|
+
|
|
25
30
|
if (dagScope === 'all' || dagScope === 'entity' || dagScope === 'block') {
|
|
26
31
|
return dagScope
|
|
27
32
|
}
|
|
33
|
+
|
|
34
|
+
// entity-bytes implies entity scope
|
|
35
|
+
if (query['entity-bytes']) {
|
|
36
|
+
return 'entity'
|
|
37
|
+
}
|
|
38
|
+
|
|
28
39
|
return 'all'
|
|
29
40
|
}
|
|
30
41
|
|
|
@@ -37,21 +48,28 @@ export class CarPlugin extends BasePlugin {
|
|
|
37
48
|
|
|
38
49
|
canHandle (context: PluginContext): boolean {
|
|
39
50
|
this.log('checking if we can handle %c with accept %s', context.cid, context.accept)
|
|
51
|
+
|
|
40
52
|
if (context.byteRangeContext == null) {
|
|
41
53
|
return false
|
|
42
54
|
}
|
|
55
|
+
|
|
43
56
|
if (context.pathDetails == null) {
|
|
44
57
|
return false
|
|
45
58
|
}
|
|
46
59
|
|
|
47
|
-
return context.accept?.startsWith('application/vnd.ipld.car') === true || context.query.format === 'car' // application/vnd.ipld.car
|
|
60
|
+
return context.accept?.mimeType.startsWith('application/vnd.ipld.car') === true || context.query.format === 'car' // application/vnd.ipld.car
|
|
48
61
|
}
|
|
49
62
|
|
|
50
63
|
async handle (context: PluginContext & Required<Pick<PluginContext, 'byteRangeContext'>>): Promise<Response> {
|
|
51
|
-
const { options, pathDetails, cid } = context
|
|
64
|
+
const { options, pathDetails, cid, query, accept } = context
|
|
65
|
+
|
|
66
|
+
const order = accept?.options.order === 'dfs' ? 'dfs' : 'unk'
|
|
67
|
+
const duplicates = accept?.options.dups !== 'n'
|
|
68
|
+
|
|
52
69
|
if (pathDetails == null) {
|
|
53
70
|
throw new Error('attempted to handle request for car with no path details')
|
|
54
71
|
}
|
|
72
|
+
|
|
55
73
|
const { getBlockstore, helia } = this.pluginOptions
|
|
56
74
|
context.reqFormat = 'car'
|
|
57
75
|
context.query.download = true
|
|
@@ -63,46 +81,52 @@ export class CarPlugin extends BasePlugin {
|
|
|
63
81
|
getCodec: helia.getCodec,
|
|
64
82
|
logger: helia.logger
|
|
65
83
|
})
|
|
66
|
-
|
|
84
|
+
|
|
67
85
|
const carExportOptions: ExportCarOptions = {
|
|
68
|
-
...options
|
|
86
|
+
...options,
|
|
87
|
+
includeTraversalBlocks: true
|
|
69
88
|
}
|
|
70
|
-
|
|
71
|
-
|
|
89
|
+
|
|
90
|
+
if (!duplicates) {
|
|
91
|
+
carExportOptions.blockFilter = createScalableCuckooFilter(1024)
|
|
72
92
|
}
|
|
93
|
+
|
|
94
|
+
if (pathDetails.ipfsRoots.length > 1) {
|
|
95
|
+
carExportOptions.traversal = new CIDPath(pathDetails.ipfsRoots)
|
|
96
|
+
}
|
|
97
|
+
|
|
73
98
|
const dagScope = getDagScope(context)
|
|
74
|
-
|
|
75
|
-
|
|
99
|
+
const target = pathDetails.terminalElement.cid ?? cid
|
|
100
|
+
|
|
76
101
|
if (dagScope === 'block') {
|
|
77
102
|
carExportOptions.exporter = new BlockExporter()
|
|
78
103
|
} else if (dagScope === 'entity') {
|
|
79
|
-
// if its unixFS, we need to enumerate a directory, or get all blocks
|
|
80
|
-
|
|
81
|
-
|
|
104
|
+
// if its unixFS, we need to enumerate a directory, or get all/some blocks
|
|
105
|
+
// for the entity, otherwise, use blockExporter
|
|
106
|
+
if (target.code === dagPbCode) {
|
|
107
|
+
const options: UnixFSExporterOptions = {
|
|
108
|
+
listingOnly: true
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const slice = getOffsetAndLength(pathDetails.terminalElement, query['entity-bytes']?.toString())
|
|
112
|
+
options.offset = slice.offset
|
|
113
|
+
options.length = slice.length
|
|
114
|
+
|
|
115
|
+
carExportOptions.exporter = new UnixFSExporter(options)
|
|
82
116
|
} else {
|
|
83
117
|
carExportOptions.exporter = new BlockExporter()
|
|
84
118
|
}
|
|
85
119
|
} else {
|
|
86
120
|
carExportOptions.exporter = new SubgraphExporter()
|
|
87
121
|
}
|
|
88
|
-
const { writer, out } = CarWriter.create(root)
|
|
89
|
-
const iter = async function * (): AsyncIterable<Uint8Array> {
|
|
90
|
-
for await (const buf of out) {
|
|
91
|
-
yield buf
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
122
|
|
|
95
|
-
|
|
96
|
-
c.export(cid, writer, carExportOptions)
|
|
97
|
-
.catch((err) => {
|
|
98
|
-
this.log.error('error exporting car - %e', err)
|
|
99
|
-
})
|
|
100
|
-
// export will close the writer when it's done, no finally needed.
|
|
123
|
+
context.byteRangeContext.setBody(toBrowserReadableStream(c.export(target, carExportOptions)))
|
|
101
124
|
|
|
102
|
-
context.byteRangeContext.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
125
|
+
const response = okRangeResponse(context.resource, context.byteRangeContext.getBody('application/vnd.ipld.car; version=1'), {
|
|
126
|
+
byteRangeContext: context.byteRangeContext,
|
|
127
|
+
log: this.log
|
|
128
|
+
})
|
|
129
|
+
response.headers.set('content-type', context.byteRangeContext.getContentType() ?? `application/vnd.ipld.car; version=1; order=${order}; dups=${duplicates ? 'y' : 'n'}`)
|
|
106
130
|
|
|
107
131
|
return response
|
|
108
132
|
}
|
|
@@ -62,7 +62,7 @@ export class DagCborHtmlPreviewPlugin extends BasePlugin {
|
|
|
62
62
|
return false
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
if (accept == null || !accept.includes('text/html')) {
|
|
65
|
+
if (accept == null || !accept?.mimeType.includes('text/html')) {
|
|
66
66
|
return false
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -97,7 +97,7 @@ export class DagCborHtmlPreviewPlugin extends BasePlugin {
|
|
|
97
97
|
})
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
getHtml ({ path, obj, cid }: { path
|
|
100
|
+
getHtml ({ path, obj, cid }: { path?: string, obj: Record<string, any>, cid: CID }): string {
|
|
101
101
|
const style = `
|
|
102
102
|
:root {
|
|
103
103
|
--sans-serif: "Plex", system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif;
|
|
@@ -30,7 +30,7 @@ export class DagCborPlugin extends BasePlugin {
|
|
|
30
30
|
return false
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
if (accept != null && accept.
|
|
33
|
+
if (accept != null && accept.mimeType === 'text/html' && plugins.includes('dag-cbor-plugin-html-preview')) {
|
|
34
34
|
// let the dag-cbor-html-preview plugin handle it
|
|
35
35
|
return false
|
|
36
36
|
}
|
|
@@ -47,10 +47,10 @@ export class DagCborPlugin extends BasePlugin {
|
|
|
47
47
|
|
|
48
48
|
let body: string | Uint8Array
|
|
49
49
|
|
|
50
|
-
if (accept === 'application/octet-stream' || accept === 'application/vnd.ipld.dag-cbor' || accept === 'application/cbor') {
|
|
50
|
+
if (accept?.mimeType === 'application/octet-stream' || accept?.mimeType === 'application/vnd.ipld.dag-cbor' || accept?.mimeType === 'application/cbor') {
|
|
51
51
|
// skip decoding
|
|
52
52
|
body = block
|
|
53
|
-
} else if (accept === 'application/vnd.ipld.dag-json') {
|
|
53
|
+
} else if (accept?.mimeType === 'application/vnd.ipld.dag-json') {
|
|
54
54
|
try {
|
|
55
55
|
// if vnd.ipld.dag-json has been specified, convert to the format - note
|
|
56
56
|
// that this supports more data types than regular JSON, the content-type
|
|
@@ -65,7 +65,7 @@ export class DagCborPlugin extends BasePlugin {
|
|
|
65
65
|
try {
|
|
66
66
|
body = dagCborToSafeJSON(block)
|
|
67
67
|
} catch (err) {
|
|
68
|
-
if (accept === 'application/json') {
|
|
68
|
+
if (accept?.mimeType === 'application/json') {
|
|
69
69
|
this.log('could not decode DAG-CBOR as JSON-safe, but the client sent "Accept: application/json"', err)
|
|
70
70
|
|
|
71
71
|
return notAcceptableResponse(resource)
|
|
@@ -78,7 +78,7 @@ export class DagCborPlugin extends BasePlugin {
|
|
|
78
78
|
|
|
79
79
|
context.byteRangeContext.setBody(body)
|
|
80
80
|
|
|
81
|
-
const responseContentType = accept ?? (body instanceof Uint8Array ? 'application/octet-stream' : 'application/json')
|
|
81
|
+
const responseContentType = accept?.mimeType ?? (body instanceof Uint8Array ? 'application/octet-stream' : 'application/json')
|
|
82
82
|
const response = okRangeResponse(resource, context.byteRangeContext.getBody(responseContentType), { byteRangeContext: context.byteRangeContext, log: this.log })
|
|
83
83
|
|
|
84
84
|
response.headers.set('content-type', context.byteRangeContext.getContentType() ?? responseContentType)
|
|
@@ -55,8 +55,8 @@ export class DagPbPlugin extends BasePlugin {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
async handle (context: PluginContext & Required<Pick<PluginContext, 'byteRangeContext' | 'pathDetails'>>): Promise<Response | null> {
|
|
58
|
-
const { cid, options,
|
|
59
|
-
const {
|
|
58
|
+
const { cid, options, pathDetails, query } = context
|
|
59
|
+
const { contentTypeParser, helia, getBlockstore } = this.pluginOptions
|
|
60
60
|
const log = this.log
|
|
61
61
|
let resource = context.resource
|
|
62
62
|
let path = context.path
|
|
@@ -93,10 +93,10 @@ export class DagPbPlugin extends BasePlugin {
|
|
|
93
93
|
try {
|
|
94
94
|
log.trace('found directory at %c/%s, looking for index.html', cid, path)
|
|
95
95
|
|
|
96
|
-
const entry = await
|
|
96
|
+
const entry = await context.serverTiming.time('exporter-dir', '', exporter(`/ipfs/${dirCid}/${rootFilePath}`, helia.blockstore, {
|
|
97
97
|
signal: options?.signal,
|
|
98
98
|
onProgress: options?.onProgress
|
|
99
|
-
})
|
|
99
|
+
}))
|
|
100
100
|
|
|
101
101
|
log.trace('found root file at %c/%s with cid %c', dirCid, rootFilePath, entry.cid)
|
|
102
102
|
path = rootFilePath
|
|
@@ -136,10 +136,10 @@ export class DagPbPlugin extends BasePlugin {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
try {
|
|
139
|
-
const entry = await
|
|
139
|
+
const entry = await context.serverTiming.time('exporter-file', '', exporter(resolvedCID, helia.blockstore, {
|
|
140
140
|
signal: options?.signal,
|
|
141
141
|
onProgress: options?.onProgress
|
|
142
|
-
})
|
|
142
|
+
}))
|
|
143
143
|
|
|
144
144
|
let firstChunk: Uint8Array
|
|
145
145
|
let contentType: string
|
|
@@ -152,13 +152,13 @@ export class DagPbPlugin extends BasePlugin {
|
|
|
152
152
|
})
|
|
153
153
|
log('got async iterator for %c/%s', cid, path)
|
|
154
154
|
|
|
155
|
-
const streamAndFirstChunk = await
|
|
155
|
+
const streamAndFirstChunk = await context.serverTiming.time('stream-and-chunk', '', getStreamFromAsyncIterable(asyncIter, path ?? '', this.pluginOptions.logger, {
|
|
156
156
|
onProgress: options?.onProgress,
|
|
157
157
|
signal: options?.signal
|
|
158
|
-
})
|
|
158
|
+
}))
|
|
159
159
|
const stream = streamAndFirstChunk.stream
|
|
160
160
|
firstChunk = streamAndFirstChunk.firstChunk
|
|
161
|
-
contentType = await
|
|
161
|
+
contentType = await context.serverTiming.time('get-content-type', '', getContentType({ filename: query.filename, bytes: firstChunk, path, contentTypeParser, log }))
|
|
162
162
|
|
|
163
163
|
byteRangeContext.setBody(stream)
|
|
164
164
|
}
|
|
@@ -186,8 +186,8 @@ export class DagPbPlugin extends BasePlugin {
|
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
private async handleRangeRequest (context: PluginContext & Required<Pick<PluginContext, 'byteRangeContext' | 'pathDetails'>>, entry: UnixFSEntry): Promise<string> {
|
|
189
|
-
const { path, byteRangeContext, options
|
|
190
|
-
const {
|
|
189
|
+
const { path, byteRangeContext, options } = context
|
|
190
|
+
const { contentTypeParser } = this.pluginOptions
|
|
191
191
|
const log = this.log
|
|
192
192
|
|
|
193
193
|
// get the first chunk in order to determine the content type
|
|
@@ -203,7 +203,7 @@ export class DagPbPlugin extends BasePlugin {
|
|
|
203
203
|
onProgress: options?.onProgress,
|
|
204
204
|
signal: options?.signal
|
|
205
205
|
})
|
|
206
|
-
const contentType = await
|
|
206
|
+
const contentType = await context.serverTiming.time('get-content-type', '', getContentType({ bytes: firstChunk, path, contentTypeParser, log }))
|
|
207
207
|
|
|
208
208
|
byteRangeContext?.setBody((range): AsyncGenerator<Uint8Array, void, unknown> => {
|
|
209
209
|
if (options?.signal?.aborted) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { code as dagCborCode } from '@ipld/dag-cbor'
|
|
2
2
|
import { code as dagPbCode } from '@ipld/dag-pb'
|
|
3
|
+
import { CODEC_IDENTITY } from '../constants.ts'
|
|
3
4
|
import { handlePathWalking } from '../utils/walk-path.js'
|
|
4
5
|
import { BasePlugin } from './plugin-base.js'
|
|
5
6
|
import type { PluginContext } from './types.js'
|
|
@@ -23,16 +24,16 @@ export class DagWalkPlugin extends BasePlugin {
|
|
|
23
24
|
return false
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
return (cid.code === dagPbCode || cid.code === dagCborCode)
|
|
27
|
+
return (cid.code === dagPbCode || cid.code === dagCborCode || cid.multihash.code === CODEC_IDENTITY)
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
async handle (context: PluginContext): Promise<Response | null> {
|
|
30
|
-
const { cid, resource, options
|
|
31
|
-
const { getBlockstore
|
|
31
|
+
const { cid, resource, options } = context
|
|
32
|
+
const { getBlockstore } = this.pluginOptions
|
|
32
33
|
const blockstore = getBlockstore(cid, resource, options?.session ?? true, options)
|
|
33
34
|
|
|
34
35
|
// TODO: migrate handlePathWalking into this plugin
|
|
35
|
-
const pathDetails = await
|
|
36
|
+
const pathDetails = await context.serverTiming.time('path-walking', '', handlePathWalking({ ...context, blockstore, log: this.log }))
|
|
36
37
|
|
|
37
38
|
if (pathDetails instanceof Response) {
|
|
38
39
|
this.log.trace('path walking failed')
|