@helia/verified-fetch 8.0.3 → 8.1.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.
Files changed (60) hide show
  1. package/dist/index.min.js +53 -53
  2. package/dist/index.min.js.map +4 -4
  3. package/dist/src/constants.d.ts +1 -0
  4. package/dist/src/constants.d.ts.map +1 -1
  5. package/dist/src/constants.js +1 -0
  6. package/dist/src/constants.js.map +1 -1
  7. package/dist/src/index.d.ts +3 -3
  8. package/dist/src/index.d.ts.map +1 -1
  9. package/dist/src/index.js +1 -1
  10. package/dist/src/index.js.map +1 -1
  11. package/dist/src/url-resolver.d.ts.map +1 -1
  12. package/dist/src/url-resolver.js +1 -13
  13. package/dist/src/url-resolver.js.map +1 -1
  14. package/dist/src/utils/canonical-uri.d.ts +9 -0
  15. package/dist/src/utils/canonical-uri.d.ts.map +1 -0
  16. package/dist/src/utils/canonical-uri.js +157 -0
  17. package/dist/src/utils/canonical-uri.js.map +1 -0
  18. package/dist/src/utils/ipfs-uri.d.ts +8 -0
  19. package/dist/src/utils/ipfs-uri.d.ts.map +1 -0
  20. package/dist/src/utils/ipfs-uri.js +10 -0
  21. package/dist/src/utils/ipfs-uri.js.map +1 -0
  22. package/dist/src/utils/ipfs-url-to-ipfs-path.d.ts +5 -0
  23. package/dist/src/utils/ipfs-url-to-ipfs-path.d.ts.map +1 -0
  24. package/dist/src/utils/ipfs-url-to-ipfs-path.js +16 -0
  25. package/dist/src/utils/ipfs-url-to-ipfs-path.js.map +1 -0
  26. package/dist/src/utils/libp2p-defaults.browser.d.ts +2 -1
  27. package/dist/src/utils/libp2p-defaults.browser.d.ts.map +1 -1
  28. package/dist/src/utils/libp2p-defaults.browser.js +13 -8
  29. package/dist/src/utils/libp2p-defaults.browser.js.map +1 -1
  30. package/dist/src/utils/libp2p-defaults.d.ts +2 -1
  31. package/dist/src/utils/libp2p-defaults.d.ts.map +1 -1
  32. package/dist/src/utils/libp2p-defaults.js +3 -7
  33. package/dist/src/utils/libp2p-defaults.js.map +1 -1
  34. package/dist/src/utils/parse-resource.d.ts.map +1 -1
  35. package/dist/src/utils/parse-resource.js +2 -1
  36. package/dist/src/utils/parse-resource.js.map +1 -1
  37. package/dist/src/utils/x-ipfs-path.d.ts +11 -0
  38. package/dist/src/utils/x-ipfs-path.d.ts.map +1 -0
  39. package/dist/src/utils/x-ipfs-path.js +30 -0
  40. package/dist/src/utils/x-ipfs-path.js.map +1 -0
  41. package/dist/src/verified-fetch.d.ts.map +1 -1
  42. package/dist/src/verified-fetch.js +37 -11
  43. package/dist/src/verified-fetch.js.map +1 -1
  44. package/package.json +1 -2
  45. package/src/constants.ts +1 -0
  46. package/src/index.ts +4 -4
  47. package/src/url-resolver.ts +1 -17
  48. package/src/utils/canonical-uri.ts +184 -0
  49. package/src/utils/ipfs-uri.ts +9 -0
  50. package/src/utils/ipfs-url-to-ipfs-path.ts +18 -0
  51. package/src/utils/libp2p-defaults.browser.ts +14 -10
  52. package/src/utils/libp2p-defaults.ts +5 -9
  53. package/src/utils/parse-resource.ts +2 -1
  54. package/src/utils/x-ipfs-path.ts +34 -0
  55. package/src/verified-fetch.ts +37 -12
  56. package/dist/src/utils/ipfs-path-to-string.d.ts +0 -6
  57. package/dist/src/utils/ipfs-path-to-string.d.ts.map +0 -1
  58. package/dist/src/utils/ipfs-path-to-string.js +0 -10
  59. package/dist/src/utils/ipfs-path-to-string.js.map +0 -1
  60. package/src/utils/ipfs-path-to-string.ts +0 -9
@@ -3,8 +3,7 @@ import { ipnsResolver } from '@helia/ipns'
3
3
  import { isPeerId, isPublicKey } from '@libp2p/interface'
4
4
  import { CID } from 'multiformats/cid'
5
5
  import { CustomProgressEvent } from 'progress-events'
6
- import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
7
- import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
6
+ import { MAX_HEADER_VALUE_LENGTH } from './constants.ts'
8
7
  import { CarPlugin } from './plugins/plugin-handle-car.ts'
9
8
  import { IpldPlugin } from './plugins/plugin-handle-ipld.ts'
10
9
  import { IpnsRecordPlugin } from './plugins/plugin-handle-ipns-record.ts'
@@ -19,10 +18,12 @@ import { errorToObject } from './utils/error-to-object.ts'
19
18
  import { errorToResponse } from './utils/error-to-response.ts'
20
19
  import { getETag, ifNoneMatches } from './utils/get-e-tag.ts'
21
20
  import { getRangeHeader } from './utils/get-range-header.ts'
21
+ import { toIpfsUri } from './utils/ipfs-uri.ts'
22
22
  import { stringToIpfsUrl } from './utils/parse-resource.ts'
23
23
  import { setCacheControlHeader } from './utils/response-headers.ts'
24
24
  import { notAcceptableResponse, notImplementedResponse, notModifiedResponse } from './utils/responses.ts'
25
25
  import { ServerTiming } from './utils/server-timing.ts'
26
+ import { toXIpfsPath } from './utils/x-ipfs-path.ts'
26
27
  import type { AcceptHeader, CIDDetail, ContentTypeParser, CreateVerifiedFetchOptions, Resource, ResourceDetail, VerifiedFetchInit as VerifiedFetchOptions, VerifiedFetchPlugin, PluginContext, PluginOptions } from './index.ts'
27
28
  import type { DNSLink } from '@helia/dnslink'
28
29
  import type { Helia } from '@helia/interface'
@@ -163,7 +164,15 @@ export class VerifiedFetch {
163
164
  })
164
165
  }
165
166
 
166
- const url = this.parseResource(resource)
167
+ let url: URL
168
+
169
+ try {
170
+ url = this.parseResource(resource)
171
+ } catch (err: any) {
172
+ return this.handleFinalResponse(errorToResponse(resource, err, opts), withServerTiming, {
173
+ serverTiming
174
+ })
175
+ }
167
176
 
168
177
  if (url.protocol === 'ipfs:' && url.pathname === '') {
169
178
  // if we don't need to resolve an IPNS names or traverse a DAG, we can
@@ -429,15 +438,31 @@ export class VerifiedFetch {
429
438
  }
430
439
 
431
440
  if (context?.terminalElement?.cid != null && context?.url != null) {
432
- // headers can ony contain extended ASCII but IPFS paths can be unicode
433
- const decodedPath = context.url.pathname.split('/')
434
- .map(component => decodeURIComponent(component))
435
- .join('/')
436
- .trim()
437
-
438
- const path = uint8ArrayToString(uint8ArrayFromString(decodedPath, 'ascii'), 'ascii')
441
+ const ipfsUri = toIpfsUri(context.url)
442
+
443
+ // the value is ASCII-only so string length equals byte length; a value
444
+ // of exactly MAX_HEADER_VALUE_LENGTH bytes is still sent
445
+ if (ipfsUri != null && ipfsUri.length <= MAX_HEADER_VALUE_LENGTH) {
446
+ try {
447
+ response.headers.set('ipfs-uri', ipfsUri)
448
+ } catch (err) {
449
+ this.log.error('could not set ipfs-uri to "%s"', ipfsUri)
450
+ }
451
+ }
439
452
 
440
- response.headers.set('x-ipfs-path', `/${context.url.protocol === 'ipfs:' ? 'ipfs' : 'ipns'}/${context?.url.hostname}${path === '/' ? '' : path}`)
453
+ // x-ipfs-path is deprecated by IPIP-0548 in favour of ipfs-uri, and is
454
+ // kept for clients that still read it. It is omitted for content paths
455
+ // that an HTTP field value cannot carry, e.g. a file name with
456
+ // non-ASCII bytes
457
+ const ipfsPath = toXIpfsPath(context.url)
458
+
459
+ if (ipfsPath != null && ipfsPath.length <= MAX_HEADER_VALUE_LENGTH) {
460
+ try {
461
+ response.headers.set('x-ipfs-path', ipfsPath)
462
+ } catch (err) {
463
+ this.log.error('could not set x-ipfs-path to "%s"', ipfsPath)
464
+ }
465
+ }
441
466
  }
442
467
 
443
468
  // set CORS headers. If hosting your own gateway with verified-fetch behind
@@ -449,7 +474,7 @@ export class VerifiedFetch {
449
474
  response.headers.set('access-control-allow-origin', '*')
450
475
  response.headers.set('access-control-allow-methods', 'GET, HEAD, OPTIONS')
451
476
  response.headers.set('access-control-allow-headers', 'Content-Type, Range, User-Agent, X-Requested-With')
452
- response.headers.set('access-control-expose-headers', 'Content-Range, Content-Length, X-Ipfs-Path, X-Ipfs-Roots, X-Chunked-Output, X-Stream-Output')
477
+ response.headers.set('access-control-expose-headers', 'Content-Range, Content-Length, Ipfs-Uri, X-Ipfs-Path, X-Ipfs-Roots, X-Chunked-Output, X-Stream-Output')
453
478
 
454
479
  if (context?.terminalElement?.cid != null && response.headers.get('etag') == null) {
455
480
  const etag = getETag({
@@ -1,6 +0,0 @@
1
- /**
2
- * Joins an array of strings as an IPFS path and URI encodes individual
3
- * components
4
- */
5
- export declare function uriEncodeIPFSPath(str: string): string;
6
- //# sourceMappingURL=ipfs-path-to-string.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ipfs-path-to-string.d.ts","sourceRoot":"","sources":["../../../src/utils/ipfs-path-to-string.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAItD"}
@@ -1,10 +0,0 @@
1
- /**
2
- * Joins an array of strings as an IPFS path and URI encodes individual
3
- * components
4
- */
5
- export function uriEncodeIPFSPath(str) {
6
- return str.split('/')
7
- .map(p => encodeURIComponent(p))
8
- .join('/');
9
- }
10
- //# sourceMappingURL=ipfs-path-to-string.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ipfs-path-to-string.js","sourceRoot":"","sources":["../../../src/utils/ipfs-path-to-string.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAE,GAAW;IAC5C,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;SAClB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;SAC/B,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC"}
@@ -1,9 +0,0 @@
1
- /**
2
- * Joins an array of strings as an IPFS path and URI encodes individual
3
- * components
4
- */
5
- export function uriEncodeIPFSPath (str: string): string {
6
- return str.split('/')
7
- .map(p => encodeURIComponent(p))
8
- .join('/')
9
- }