@helia/verified-fetch 4.1.1 → 5.0.1

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 (231) hide show
  1. package/README.md +6 -40
  2. package/dist/index.min.js +73 -534
  3. package/dist/index.min.js.map +4 -4
  4. package/dist/src/constants.d.ts +2 -0
  5. package/dist/src/constants.d.ts.map +1 -1
  6. package/dist/src/constants.js +2 -0
  7. package/dist/src/constants.js.map +1 -1
  8. package/dist/src/index.d.ts +162 -68
  9. package/dist/src/index.d.ts.map +1 -1
  10. package/dist/src/index.js +7 -40
  11. package/dist/src/index.js.map +1 -1
  12. package/dist/src/plugins/index.d.ts +0 -5
  13. package/dist/src/plugins/index.d.ts.map +1 -1
  14. package/dist/src/plugins/index.js +0 -4
  15. package/dist/src/plugins/index.js.map +1 -1
  16. package/dist/src/plugins/plugin-base.d.ts +8 -9
  17. package/dist/src/plugins/plugin-base.d.ts.map +1 -1
  18. package/dist/src/plugins/plugin-base.js +5 -6
  19. package/dist/src/plugins/plugin-base.js.map +1 -1
  20. package/dist/src/plugins/plugin-handle-car.d.ts +3 -3
  21. package/dist/src/plugins/plugin-handle-car.d.ts.map +1 -1
  22. package/dist/src/plugins/plugin-handle-car.js +38 -39
  23. package/dist/src/plugins/plugin-handle-car.js.map +1 -1
  24. package/dist/src/plugins/plugin-handle-ipld.d.ts +12 -0
  25. package/dist/src/plugins/plugin-handle-ipld.d.ts.map +1 -0
  26. package/dist/src/plugins/plugin-handle-ipld.js +83 -0
  27. package/dist/src/plugins/plugin-handle-ipld.js.map +1 -0
  28. package/dist/src/plugins/plugin-handle-ipns-record.d.ts +3 -3
  29. package/dist/src/plugins/plugin-handle-ipns-record.d.ts.map +1 -1
  30. package/dist/src/plugins/plugin-handle-ipns-record.js +25 -34
  31. package/dist/src/plugins/plugin-handle-ipns-record.js.map +1 -1
  32. package/dist/src/plugins/plugin-handle-tar.d.ts +3 -3
  33. package/dist/src/plugins/plugin-handle-tar.d.ts.map +1 -1
  34. package/dist/src/plugins/plugin-handle-tar.js +20 -22
  35. package/dist/src/plugins/plugin-handle-tar.js.map +1 -1
  36. package/dist/src/plugins/plugin-handle-unixfs.d.ts +14 -0
  37. package/dist/src/plugins/plugin-handle-unixfs.d.ts.map +1 -0
  38. package/dist/src/plugins/plugin-handle-unixfs.js +180 -0
  39. package/dist/src/plugins/plugin-handle-unixfs.js.map +1 -0
  40. package/dist/src/plugins/types.d.ts +1 -77
  41. package/dist/src/plugins/types.d.ts.map +1 -1
  42. package/dist/src/url-resolver.d.ts +29 -11
  43. package/dist/src/url-resolver.d.ts.map +1 -1
  44. package/dist/src/url-resolver.js +152 -74
  45. package/dist/src/url-resolver.js.map +1 -1
  46. package/dist/src/utils/content-type-parser.d.ts.map +1 -1
  47. package/dist/src/utils/content-type-parser.js +4 -3
  48. package/dist/src/utils/content-type-parser.js.map +1 -1
  49. package/dist/src/utils/content-types.d.ts +26 -0
  50. package/dist/src/utils/content-types.d.ts.map +1 -0
  51. package/dist/src/utils/content-types.js +137 -0
  52. package/dist/src/utils/content-types.js.map +1 -0
  53. package/dist/src/utils/convert-output.d.ts +17 -0
  54. package/dist/src/utils/convert-output.d.ts.map +1 -0
  55. package/dist/src/utils/convert-output.js +176 -0
  56. package/dist/src/utils/convert-output.js.map +1 -0
  57. package/dist/src/utils/error-to-response.d.ts +3 -0
  58. package/dist/src/utils/error-to-response.d.ts.map +1 -0
  59. package/dist/src/utils/error-to-response.js +40 -0
  60. package/dist/src/utils/error-to-response.js.map +1 -0
  61. package/dist/src/utils/get-content-disposition-filename.d.ts +1 -1
  62. package/dist/src/utils/get-content-disposition-filename.d.ts.map +1 -1
  63. package/dist/src/utils/get-content-disposition-filename.js +4 -0
  64. package/dist/src/utils/get-content-disposition-filename.js.map +1 -1
  65. package/dist/src/utils/get-e-tag.d.ts +20 -15
  66. package/dist/src/utils/get-e-tag.d.ts.map +1 -1
  67. package/dist/src/utils/get-e-tag.js +8 -22
  68. package/dist/src/utils/get-e-tag.js.map +1 -1
  69. package/dist/src/utils/get-offset-and-length.d.ts +12 -2
  70. package/dist/src/utils/get-offset-and-length.d.ts.map +1 -1
  71. package/dist/src/utils/get-offset-and-length.js +63 -21
  72. package/dist/src/utils/get-offset-and-length.js.map +1 -1
  73. package/dist/src/utils/get-range-header.d.ts +22 -0
  74. package/dist/src/utils/get-range-header.d.ts.map +1 -0
  75. package/dist/src/utils/get-range-header.js +69 -0
  76. package/dist/src/utils/get-range-header.js.map +1 -0
  77. package/dist/src/utils/parse-url-string.d.ts +2 -1
  78. package/dist/src/utils/parse-url-string.d.ts.map +1 -1
  79. package/dist/src/utils/parse-url-string.js +46 -71
  80. package/dist/src/utils/parse-url-string.js.map +1 -1
  81. package/dist/src/utils/resource-to-cache-key.d.ts +3 -3
  82. package/dist/src/utils/resource-to-cache-key.js +5 -5
  83. package/dist/src/utils/resource-to-cache-key.js.map +1 -1
  84. package/dist/src/utils/response-headers.d.ts +4 -14
  85. package/dist/src/utils/response-headers.d.ts.map +1 -1
  86. package/dist/src/utils/response-headers.js +36 -36
  87. package/dist/src/utils/response-headers.js.map +1 -1
  88. package/dist/src/utils/responses.d.ts +30 -11
  89. package/dist/src/utils/responses.d.ts.map +1 -1
  90. package/dist/src/utils/responses.js +146 -39
  91. package/dist/src/utils/responses.js.map +1 -1
  92. package/dist/src/verified-fetch.d.ts +16 -15
  93. package/dist/src/verified-fetch.d.ts.map +1 -1
  94. package/dist/src/verified-fetch.js +302 -238
  95. package/dist/src/verified-fetch.js.map +1 -1
  96. package/dist/typedoc-urls.json +64 -45
  97. package/package.json +4 -3
  98. package/src/constants.ts +3 -0
  99. package/src/index.ts +199 -68
  100. package/src/plugins/index.ts +0 -6
  101. package/src/plugins/plugin-base.ts +8 -10
  102. package/src/plugins/plugin-handle-car.ts +48 -46
  103. package/src/plugins/plugin-handle-ipld.ts +93 -0
  104. package/src/plugins/plugin-handle-ipns-record.ts +31 -41
  105. package/src/plugins/plugin-handle-tar.ts +25 -29
  106. package/src/plugins/plugin-handle-unixfs.ts +217 -0
  107. package/src/plugins/types.ts +0 -86
  108. package/src/url-resolver.ts +197 -83
  109. package/src/utils/content-type-parser.ts +4 -3
  110. package/src/utils/content-types.ts +159 -0
  111. package/src/utils/convert-output.ts +187 -0
  112. package/src/utils/error-to-response.ts +49 -0
  113. package/src/utils/get-content-disposition-filename.ts +7 -1
  114. package/src/utils/get-e-tag.ts +26 -35
  115. package/src/utils/get-offset-and-length.ts +75 -21
  116. package/src/utils/get-range-header.ts +107 -0
  117. package/src/utils/parse-url-string.ts +51 -80
  118. package/src/utils/resource-to-cache-key.ts +5 -5
  119. package/src/utils/response-headers.ts +40 -41
  120. package/src/utils/responses.ts +186 -45
  121. package/src/verified-fetch.ts +353 -270
  122. package/dist/src/plugins/plugin-handle-byte-range-context.d.ts +0 -14
  123. package/dist/src/plugins/plugin-handle-byte-range-context.d.ts.map +0 -1
  124. package/dist/src/plugins/plugin-handle-byte-range-context.js +0 -25
  125. package/dist/src/plugins/plugin-handle-byte-range-context.js.map +0 -1
  126. package/dist/src/plugins/plugin-handle-cbor.d.ts +0 -17
  127. package/dist/src/plugins/plugin-handle-cbor.d.ts.map +0 -1
  128. package/dist/src/plugins/plugin-handle-cbor.js +0 -94
  129. package/dist/src/plugins/plugin-handle-cbor.js.map +0 -1
  130. package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.d.ts +0 -27
  131. package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.d.ts.map +0 -1
  132. package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.js +0 -279
  133. package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.js.map +0 -1
  134. package/dist/src/plugins/plugin-handle-dag-cbor.d.ts +0 -17
  135. package/dist/src/plugins/plugin-handle-dag-cbor.d.ts.map +0 -1
  136. package/dist/src/plugins/plugin-handle-dag-cbor.js +0 -66
  137. package/dist/src/plugins/plugin-handle-dag-cbor.js.map +0 -1
  138. package/dist/src/plugins/plugin-handle-dag-pb.d.ts +0 -17
  139. package/dist/src/plugins/plugin-handle-dag-pb.d.ts.map +0 -1
  140. package/dist/src/plugins/plugin-handle-dag-pb.js +0 -209
  141. package/dist/src/plugins/plugin-handle-dag-pb.js.map +0 -1
  142. package/dist/src/plugins/plugin-handle-dag-walk.d.ts +0 -21
  143. package/dist/src/plugins/plugin-handle-dag-walk.d.ts.map +0 -1
  144. package/dist/src/plugins/plugin-handle-dag-walk.js +0 -95
  145. package/dist/src/plugins/plugin-handle-dag-walk.js.map +0 -1
  146. package/dist/src/plugins/plugin-handle-dir-index-html.d.ts +0 -10
  147. package/dist/src/plugins/plugin-handle-dir-index-html.d.ts.map +0 -1
  148. package/dist/src/plugins/plugin-handle-dir-index-html.js +0 -59
  149. package/dist/src/plugins/plugin-handle-dir-index-html.js.map +0 -1
  150. package/dist/src/plugins/plugin-handle-json.d.ts +0 -12
  151. package/dist/src/plugins/plugin-handle-json.d.ts.map +0 -1
  152. package/dist/src/plugins/plugin-handle-json.js +0 -73
  153. package/dist/src/plugins/plugin-handle-json.js.map +0 -1
  154. package/dist/src/plugins/plugin-handle-raw.d.ts +0 -9
  155. package/dist/src/plugins/plugin-handle-raw.d.ts.map +0 -1
  156. package/dist/src/plugins/plugin-handle-raw.js +0 -92
  157. package/dist/src/plugins/plugin-handle-raw.js.map +0 -1
  158. package/dist/src/plugins/plugins.d.ts +0 -6
  159. package/dist/src/plugins/plugins.d.ts.map +0 -1
  160. package/dist/src/plugins/plugins.js +0 -6
  161. package/dist/src/plugins/plugins.js.map +0 -1
  162. package/dist/src/utils/byte-range-context.d.ts +0 -103
  163. package/dist/src/utils/byte-range-context.d.ts.map +0 -1
  164. package/dist/src/utils/byte-range-context.js +0 -504
  165. package/dist/src/utils/byte-range-context.js.map +0 -1
  166. package/dist/src/utils/dag-cbor-to-safe-json.d.ts +0 -15
  167. package/dist/src/utils/dag-cbor-to-safe-json.d.ts.map +0 -1
  168. package/dist/src/utils/dag-cbor-to-safe-json.js +0 -54
  169. package/dist/src/utils/dag-cbor-to-safe-json.js.map +0 -1
  170. package/dist/src/utils/dir-index-html.d.ts +0 -19
  171. package/dist/src/utils/dir-index-html.d.ts.map +0 -1
  172. package/dist/src/utils/dir-index-html.js +0 -438
  173. package/dist/src/utils/dir-index-html.js.map +0 -1
  174. package/dist/src/utils/get-peer-id-from-string.d.ts +0 -3
  175. package/dist/src/utils/get-peer-id-from-string.d.ts.map +0 -1
  176. package/dist/src/utils/get-peer-id-from-string.js +0 -10
  177. package/dist/src/utils/get-peer-id-from-string.js.map +0 -1
  178. package/dist/src/utils/get-resolved-accept-header.d.ts +0 -9
  179. package/dist/src/utils/get-resolved-accept-header.d.ts.map +0 -1
  180. package/dist/src/utils/get-resolved-accept-header.js +0 -27
  181. package/dist/src/utils/get-resolved-accept-header.js.map +0 -1
  182. package/dist/src/utils/get-stream-from-async-iterable.d.ts +0 -9
  183. package/dist/src/utils/get-stream-from-async-iterable.d.ts.map +0 -1
  184. package/dist/src/utils/get-stream-from-async-iterable.js +0 -43
  185. package/dist/src/utils/get-stream-from-async-iterable.js.map +0 -1
  186. package/dist/src/utils/handle-redirects.d.ts +0 -16
  187. package/dist/src/utils/handle-redirects.d.ts.map +0 -1
  188. package/dist/src/utils/handle-redirects.js +0 -84
  189. package/dist/src/utils/handle-redirects.js.map +0 -1
  190. package/dist/src/utils/is-accept-explicit.d.ts +0 -15
  191. package/dist/src/utils/is-accept-explicit.d.ts.map +0 -1
  192. package/dist/src/utils/is-accept-explicit.js +0 -26
  193. package/dist/src/utils/is-accept-explicit.js.map +0 -1
  194. package/dist/src/utils/request-headers.d.ts +0 -13
  195. package/dist/src/utils/request-headers.d.ts.map +0 -1
  196. package/dist/src/utils/request-headers.js +0 -63
  197. package/dist/src/utils/request-headers.js.map +0 -1
  198. package/dist/src/utils/select-output-type.d.ts +0 -17
  199. package/dist/src/utils/select-output-type.d.ts.map +0 -1
  200. package/dist/src/utils/select-output-type.js +0 -153
  201. package/dist/src/utils/select-output-type.js.map +0 -1
  202. package/dist/src/utils/tlru.d.ts +0 -15
  203. package/dist/src/utils/tlru.d.ts.map +0 -1
  204. package/dist/src/utils/tlru.js +0 -34
  205. package/dist/src/utils/tlru.js.map +0 -1
  206. package/dist/src/utils/walk-path.d.ts +0 -27
  207. package/dist/src/utils/walk-path.d.ts.map +0 -1
  208. package/dist/src/utils/walk-path.js +0 -45
  209. package/dist/src/utils/walk-path.js.map +0 -1
  210. package/src/plugins/plugin-handle-byte-range-context.ts +0 -30
  211. package/src/plugins/plugin-handle-cbor.ts +0 -107
  212. package/src/plugins/plugin-handle-dag-cbor-html-preview.ts +0 -295
  213. package/src/plugins/plugin-handle-dag-cbor.ts +0 -83
  214. package/src/plugins/plugin-handle-dag-pb.ts +0 -248
  215. package/src/plugins/plugin-handle-dag-walk.ts +0 -110
  216. package/src/plugins/plugin-handle-dir-index-html.ts +0 -72
  217. package/src/plugins/plugin-handle-json.ts +0 -80
  218. package/src/plugins/plugin-handle-raw.ts +0 -110
  219. package/src/plugins/plugins.ts +0 -5
  220. package/src/utils/byte-range-context.ts +0 -597
  221. package/src/utils/dag-cbor-to-safe-json.ts +0 -63
  222. package/src/utils/dir-index-html.ts +0 -505
  223. package/src/utils/get-peer-id-from-string.ts +0 -12
  224. package/src/utils/get-resolved-accept-header.ts +0 -42
  225. package/src/utils/get-stream-from-async-iterable.ts +0 -49
  226. package/src/utils/handle-redirects.ts +0 -109
  227. package/src/utils/is-accept-explicit.ts +0 -38
  228. package/src/utils/request-headers.ts +0 -65
  229. package/src/utils/select-output-type.ts +0 -175
  230. package/src/utils/tlru.ts +0 -42
  231. package/src/utils/walk-path.ts +0 -69
@@ -2,13 +2,12 @@ import { BlockExporter, car, CIDPath, depthFirstWalker, naturalOrderWalker, Subg
2
2
  import { code as dagPbCode } from '@ipld/dag-pb';
3
3
  import { createScalableCuckooFilter } from '@libp2p/utils';
4
4
  import toBrowserReadableStream from 'it-to-browser-readablestream';
5
- import { getOffsetAndLength } from "../utils/get-offset-and-length.js";
6
- import { notAcceptableResponse, okRangeResponse } from '../utils/responses.js';
5
+ import { CONTENT_TYPE_CAR, MEDIA_TYPE_CAR } from "../utils/content-types.js";
6
+ import { getContentDispositionFilename } from "../utils/get-content-disposition-filename.js";
7
+ import { entityBytesToOffsetAndLength } from "../utils/get-offset-and-length.js";
8
+ import { badRequestResponse, notAcceptableResponse, okResponse } from '../utils/responses.js';
7
9
  import { BasePlugin } from './plugin-base.js';
8
- function getFilename({ cid, ipfsPath, query }) {
9
- if (query.filename != null) {
10
- return query.filename;
11
- }
10
+ function getFilename(ipfsPath) {
12
11
  // convert context.ipfsPath to a filename. replace all / with _, replace prefix protocol with empty string
13
12
  const filename = ipfsPath
14
13
  .replace(/\/ipfs\//, '')
@@ -17,13 +16,13 @@ function getFilename({ cid, ipfsPath, query }) {
17
16
  .replace(/\//g, '_');
18
17
  return `${filename}.car`;
19
18
  }
20
- function getDagScope({ query }) {
21
- const dagScope = query['dag-scope'];
19
+ function getDagScope({ url }) {
20
+ const dagScope = url.searchParams.get('dag-scope');
22
21
  if (dagScope === 'all' || dagScope === 'entity' || dagScope === 'block') {
23
22
  return dagScope;
24
23
  }
25
24
  // entity-bytes implies entity scope
26
- if (query['entity-bytes']) {
25
+ if (url.searchParams.has('entity-bytes')) {
27
26
  return 'entity';
28
27
  }
29
28
  return 'all';
@@ -34,31 +33,29 @@ function getDagScope({ query }) {
34
33
  */
35
34
  export class CarPlugin extends BasePlugin {
36
35
  id = 'car-plugin';
37
- canHandle(context) {
38
- if (context.byteRangeContext == null) {
39
- return false;
40
- }
41
- if (context.pathDetails == null) {
42
- return false;
43
- }
44
- return context.accept?.mimeType.startsWith('application/vnd.ipld.car') === true || context.query.format === 'car'; // application/vnd.ipld.car
36
+ canHandle({ accept }) {
37
+ return accept.some(header => header.contentType.mediaType === MEDIA_TYPE_CAR);
45
38
  }
46
39
  async handle(context) {
47
- const { options, pathDetails, cid, query, accept, resource } = context;
48
- const order = accept?.options.order === 'dfs' || context.query['car-order'] === 'dfs' ? 'dfs' : 'unk';
49
- const duplicates = accept?.options.dups !== 'n' && context.query['car-dups'] !== 'n';
50
- if (pathDetails == null) {
51
- throw new Error('attempted to handle request for car with no path details');
40
+ const { options, url, accept, resource, blockstore, range, ipfsRoots, terminalElement } = context;
41
+ if (range != null) {
42
+ return badRequestResponse(resource, new Error('Range requests are not supported for CAR files'));
52
43
  }
44
+ const acceptCar = accept.filter(header => header.contentType.mediaType === MEDIA_TYPE_CAR).pop();
45
+ // we have already asserted that the CAR media type is present so this
46
+ // branch should never be hit
47
+ if (acceptCar == null) {
48
+ return badRequestResponse(resource, new Error('Could not find CAR media type in accept header'));
49
+ }
50
+ const order = acceptCar.options.order === 'dfs' || url.searchParams.get('car-order') === 'dfs' ? 'dfs' : 'unk';
51
+ const duplicates = acceptCar.options.dups !== 'n' && url.searchParams.get('car-dups') !== 'n';
53
52
  // TODO: `@ipld/car` only supports CARv1
54
- if (accept?.options.version === '2' || context.query['car-version'] === '2') {
55
- return notAcceptableResponse(resource, 'Only CARv1 is supported');
53
+ if (acceptCar.options.version === '2' || url.searchParams.get('car-version') === '2') {
54
+ return notAcceptableResponse(resource, [
55
+ CONTENT_TYPE_CAR
56
+ ]);
56
57
  }
57
- const { getBlockstore, helia } = this.pluginOptions;
58
- context.reqFormat = 'car';
59
- context.query.download = true;
60
- context.query.filename = getFilename(context);
61
- const blockstore = getBlockstore(cid, context.resource, options?.session ?? true, options);
58
+ const helia = this.pluginOptions.helia;
62
59
  const c = car({
63
60
  blockstore,
64
61
  getCodec: helia.getCodec,
@@ -71,11 +68,11 @@ export class CarPlugin extends BasePlugin {
71
68
  if (!duplicates) {
72
69
  carExportOptions.blockFilter = createScalableCuckooFilter(1024);
73
70
  }
74
- if (pathDetails.ipfsRoots.length > 1) {
75
- carExportOptions.traversal = new CIDPath(pathDetails.ipfsRoots);
71
+ if (ipfsRoots.length > 1) {
72
+ carExportOptions.traversal = new CIDPath(ipfsRoots);
76
73
  }
77
74
  const dagScope = getDagScope(context);
78
- const target = pathDetails.terminalElement.cid ?? cid;
75
+ const target = terminalElement.cid;
79
76
  if (dagScope === 'block') {
80
77
  carExportOptions.exporter = new BlockExporter();
81
78
  }
@@ -86,7 +83,7 @@ export class CarPlugin extends BasePlugin {
86
83
  const options = {
87
84
  listingOnly: true
88
85
  };
89
- const slice = getOffsetAndLength(pathDetails.terminalElement, query['entity-bytes']?.toString());
86
+ const slice = entityBytesToOffsetAndLength(terminalElement.size, url.searchParams.get('entity-bytes'));
90
87
  options.offset = slice.offset;
91
88
  options.length = slice.length;
92
89
  carExportOptions.exporter = new UnixFSExporter(options);
@@ -100,13 +97,15 @@ export class CarPlugin extends BasePlugin {
100
97
  walker: order === 'dfs' ? depthFirstWalker() : naturalOrderWalker()
101
98
  });
102
99
  }
103
- context.byteRangeContext.setBody(toBrowserReadableStream(c.export(target, carExportOptions)));
104
- const response = okRangeResponse(context.resource, context.byteRangeContext.getBody('application/vnd.ipld.car; version=1'), {
105
- byteRangeContext: context.byteRangeContext,
106
- log: this.log
100
+ const stream = toBrowserReadableStream(c.export(target, carExportOptions));
101
+ return okResponse(resource, stream, {
102
+ headers: {
103
+ 'content-type': `${MEDIA_TYPE_CAR}; version=1; order=${order}; dups=${duplicates ? 'y' : 'n'}`,
104
+ 'content-disposition': `attachment; ${getContentDispositionFilename(url.searchParams.get('filename') ?? getFilename(`/ipfs/${url.hostname}${url.pathname}`))}`,
105
+ 'x-content-type-options': 'nosniff',
106
+ 'accept-ranges': 'none'
107
+ }
107
108
  });
108
- response.headers.set('content-type', context.byteRangeContext.getContentType() ?? `application/vnd.ipld.car; version=1; order=${order}; dups=${duplicates ? 'y' : 'n'}`);
109
- return response;
110
109
  }
111
110
  }
112
111
  //# sourceMappingURL=plugin-handle-car.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-handle-car.js","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-car.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin-handle-car.js","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-car.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { BasePlugin } from './plugin-base.js';
2
+ import type { PluginContext } from '../index.ts';
3
+ /**
4
+ * Handles loading JSON and CBOR content
5
+ */
6
+ export declare class IpldPlugin extends BasePlugin {
7
+ readonly id = "ipld-plugin";
8
+ readonly codes: number[];
9
+ canHandle({ terminalElement, accept }: PluginContext): boolean;
10
+ handle(context: PluginContext): Promise<Response>;
11
+ }
12
+ //# sourceMappingURL=plugin-handle-ipld.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-handle-ipld.d.ts","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-ipld.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,aAAa,CAAA;AAE7D;;GAEG;AACH,qBAAa,UAAW,SAAQ,UAAU;IACxC,QAAQ,CAAC,EAAE,iBAAgB;IAC3B,QAAQ,CAAC,KAAK,WAQb;IAED,SAAS,CAAE,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,aAAa,GAAG,OAAO;IAczD,MAAM,CAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC;CAgDzD"}
@@ -0,0 +1,83 @@
1
+ import * as ipldDagCbor from '@ipld/dag-cbor';
2
+ import * as ipldDagJson from '@ipld/dag-json';
3
+ import * as dagPb from '@ipld/dag-pb';
4
+ import toBuffer from 'it-to-buffer';
5
+ import * as json from 'multiformats/codecs/json';
6
+ import * as raw from 'multiformats/codecs/raw';
7
+ import { identity } from 'multiformats/hashes/identity';
8
+ import { CODEC_CBOR } from "../constants.js";
9
+ import { getContentTypesForCid, MEDIA_TYPE_CBOR, MEDIA_TYPE_DAG_CBOR, MEDIA_TYPE_DAG_JSON, MEDIA_TYPE_JSON, MEDIA_TYPE_OCTET_STREAM, MEDIA_TYPE_RAW } from "../utils/content-types.js";
10
+ import { convertOutput } from "../utils/convert-output.js";
11
+ import { getContentDispositionFilename } from "../utils/get-content-disposition-filename.js";
12
+ import { notAcceptableResponse, okResponse, partialContentResponse } from '../utils/responses.js';
13
+ import { BasePlugin } from './plugin-base.js';
14
+ /**
15
+ * Handles loading JSON and CBOR content
16
+ */
17
+ export class IpldPlugin extends BasePlugin {
18
+ id = 'ipld-plugin';
19
+ codes = [
20
+ CODEC_CBOR,
21
+ ipldDagCbor.code,
22
+ ipldDagJson.code,
23
+ json.code,
24
+ raw.code,
25
+ dagPb.code,
26
+ identity.code
27
+ ];
28
+ canHandle({ terminalElement, accept }) {
29
+ const supportsCid = this.codes.includes(terminalElement.cid.code);
30
+ const supportsAccept = accept.length === 0 ||
31
+ accept.some(header => header.contentType.mediaType === MEDIA_TYPE_CBOR ||
32
+ header.contentType.mediaType === MEDIA_TYPE_DAG_CBOR ||
33
+ header.contentType.mediaType === MEDIA_TYPE_JSON ||
34
+ header.contentType.mediaType === MEDIA_TYPE_DAG_JSON ||
35
+ header.contentType.mediaType === MEDIA_TYPE_RAW ||
36
+ header.contentType.mediaType === MEDIA_TYPE_OCTET_STREAM);
37
+ return supportsCid && supportsAccept;
38
+ }
39
+ async handle(context) {
40
+ const { url, resource, accept, ipfsRoots, terminalElement, blockstore, options } = context;
41
+ this.log.trace('fetching %c/%s', terminalElement.cid, url.pathname);
42
+ let block;
43
+ if (terminalElement.node == null) {
44
+ block = await toBuffer(blockstore.get(terminalElement.cid, options));
45
+ }
46
+ else if (terminalElement.type === 'object' || terminalElement.type === 'raw' || terminalElement.type === 'identity') {
47
+ block = terminalElement.node;
48
+ }
49
+ else {
50
+ block = dagPb.encode(terminalElement.node);
51
+ }
52
+ let contentType;
53
+ try {
54
+ // maybe convert output to different binary format
55
+ const result = convertOutput(terminalElement.cid, block, accept);
56
+ block = result.output;
57
+ contentType = result.contentType;
58
+ }
59
+ catch (err) {
60
+ this.log.error('could not decode object from block - %e', err);
61
+ return notAcceptableResponse(resource, getContentTypesForCid(terminalElement.cid));
62
+ }
63
+ const headers = {
64
+ 'content-length': `${block.byteLength}`,
65
+ 'content-type': contentType.mediaType,
66
+ 'content-disposition': `${url.searchParams.get('download') === 'true' ? 'attachment' : contentType.disposition}; ${getContentDispositionFilename(url.searchParams.get('filename') ?? `${terminalElement.cid}${contentType.extension}`)}`,
67
+ 'x-ipfs-roots': ipfsRoots.map(cid => cid.toV1()).join(','),
68
+ 'x-content-type-options': 'nosniff',
69
+ 'accept-ranges': 'bytes'
70
+ };
71
+ if (context.range != null) {
72
+ return partialContentResponse(resource, async function* (offset, length) {
73
+ yield block.subarray(offset, offset + length);
74
+ }, context.range, block.byteLength, {
75
+ headers
76
+ });
77
+ }
78
+ return okResponse(resource, block, {
79
+ headers
80
+ });
81
+ }
82
+ }
83
+ //# sourceMappingURL=plugin-handle-ipld.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-handle-ipld.js","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-ipld.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { BasePlugin } from './plugin-base.js';
2
- import type { PluginContext } from './types.js';
2
+ import type { PluginContext } from '../index.js';
3
3
  /**
4
4
  * Accepts an `ipns://...`, `https?://<ipnsname>.ipns.<domain>`, or `https?://<domain>/ipns/...` URL as a string and
5
5
  * returns a `Response` containing a raw IPNS record.
@@ -7,7 +7,7 @@ import type { PluginContext } from './types.js';
7
7
  export declare class IpnsRecordPlugin extends BasePlugin {
8
8
  readonly id = "ipns-record-plugin";
9
9
  readonly codes: never[];
10
- canHandle({ accept, query, byteRangeContext }: PluginContext): boolean;
11
- handle(context: PluginContext & Required<Pick<PluginContext, 'byteRangeContext'>>): Promise<Response>;
10
+ canHandle({ accept }: PluginContext): boolean;
11
+ handle(context: Pick<PluginContext, 'resource' | 'url' | 'options' | 'range'>): Promise<Response>;
12
12
  }
13
13
  //# sourceMappingURL=plugin-handle-ipns-record.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-handle-ipns-record.d.ts","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-ipns-record.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAG/C;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,UAAU;IAC9C,QAAQ,CAAC,EAAE,wBAAuB;IAClC,QAAQ,CAAC,KAAK,UAAK;IAEnB,SAAS,CAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,aAAa,GAAG,OAAO;IAQjE,MAAM,CAAE,OAAO,EAAE,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC;CAgD7G"}
1
+ {"version":3,"file":"plugin-handle-ipns-record.d.ts","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-ipns-record.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAGhD;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,UAAU;IAC9C,QAAQ,CAAC,EAAE,wBAAuB;IAClC,QAAQ,CAAC,KAAK,UAAK;IAEnB,SAAS,CAAE,EAAE,MAAM,EAAE,EAAE,aAAa,GAAG,OAAO;IAIxC,MAAM,CAAE,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC;CAwCzG"}
@@ -1,6 +1,8 @@
1
+ import { peerIdFromString } from '@libp2p/peer-id';
1
2
  import { marshalIPNSRecord } from 'ipns';
2
- import { getPeerIdFromString } from '../utils/get-peer-id-from-string.js';
3
- import { badRequestResponse, okRangeResponse } from '../utils/responses.js';
3
+ import { CONTENT_TYPE_IPNS, MEDIA_TYPE_IPNS_RECORD } from "../utils/content-types.js";
4
+ import { getContentDispositionFilename } from "../utils/get-content-disposition-filename.js";
5
+ import { badRequestResponse, okResponse } from '../utils/responses.js';
4
6
  import { BasePlugin } from './plugin-base.js';
5
7
  /**
6
8
  * Accepts an `ipns://...`, `https?://<ipnsname>.ipns.<domain>`, or `https?://<domain>/ipns/...` URL as a string and
@@ -9,51 +11,40 @@ import { BasePlugin } from './plugin-base.js';
9
11
  export class IpnsRecordPlugin extends BasePlugin {
10
12
  id = 'ipns-record-plugin';
11
13
  codes = [];
12
- canHandle({ accept, query, byteRangeContext }) {
13
- if (byteRangeContext == null) {
14
- return false;
15
- }
16
- return accept?.mimeType === 'application/vnd.ipfs.ipns-record' || query.format === 'ipns-record';
14
+ canHandle({ accept }) {
15
+ return accept.some(header => header.contentType.mediaType === MEDIA_TYPE_IPNS_RECORD);
17
16
  }
18
17
  async handle(context) {
19
- const { resource, path, query, options } = context;
18
+ const { resource, url, options, range } = context;
20
19
  const { ipnsResolver } = this.pluginOptions;
21
- context.reqFormat = 'ipns-record';
22
- if (path.length > 0 || !(resource.startsWith('ipns://') || resource.includes('.ipns.') || resource.includes('/ipns/'))) {
23
- this.log.error('invalid request for IPNS name "%s" and path "%s"', resource, path);
20
+ if ((url.pathname !== '' && url.pathname !== '/') || url.protocol !== 'ipns:') {
21
+ this.log.error('invalid request for IPNS name "%s" and path "%s"', url, url.pathname);
24
22
  return badRequestResponse(resource, new Error('Invalid IPNS name'));
25
23
  }
24
+ if (range != null) {
25
+ return badRequestResponse(resource, new Error('Range requests are not supported for IPNS records'));
26
+ }
26
27
  let peerId;
27
28
  try {
28
- let peerIdString;
29
- if (resource.startsWith('ipns://')) {
30
- peerIdString = resource.replace('ipns://', '');
31
- }
32
- else if (resource.includes('/ipns/')) {
33
- peerIdString = resource.split('/ipns/')[1].split('/')[0].split('?')[0];
34
- }
35
- else {
36
- peerIdString = resource.split('.ipns.')[0].split('://')[1];
37
- }
38
- this.log.trace('trying to parse peer id from "%s"', peerIdString);
39
- peerId = getPeerIdFromString(peerIdString);
29
+ this.log.trace('trying to parse peer id from "%s"', url.hostname);
30
+ peerId = peerIdFromString(url.hostname);
40
31
  }
41
32
  catch (err) {
42
33
  this.log.error('could not parse peer id from IPNS url %s', resource, err);
43
34
  return badRequestResponse(resource, err);
44
35
  }
45
- // force download in handleFinalResponse
46
- query.filename = query.filename ?? `${peerId}.bin`;
47
- query.download = true;
48
- // @ts-expect-error progress handler types are incompatible
49
36
  const result = await ipnsResolver.resolve(peerId, options);
50
- const buf = marshalIPNSRecord(result.record);
51
- context.byteRangeContext.setBody(buf);
52
- const response = okRangeResponse(resource, context.byteRangeContext.getBody('application/vnd.ipfs.ipns-record'), { byteRangeContext: context.byteRangeContext, log: this.log });
53
- response.headers.set('content-type', context.byteRangeContext.getContentType() ?? 'application/vnd.ipfs.ipns-record');
54
- response.headers.set('content-length', buf.byteLength.toString());
55
- response.headers.set('x-ipfs-roots', result.cid.toV1().toString());
56
- return response;
37
+ const block = marshalIPNSRecord(result.record);
38
+ return okResponse(resource, block, {
39
+ headers: {
40
+ 'content-length': `${block.byteLength}`,
41
+ 'content-type': CONTENT_TYPE_IPNS.mediaType,
42
+ 'content-disposition': `attachment; ${getContentDispositionFilename(url.searchParams.get('filename') ?? `${peerId}${CONTENT_TYPE_IPNS.extension}`)}`,
43
+ 'x-ipfs-roots': result.cid.toV1().toString(),
44
+ 'cache-control': `public, max-age=${Number((result.record.ttl ?? 0n) / BigInt(1e9))}`,
45
+ 'accept-ranges': 'none'
46
+ }
47
+ });
57
48
  }
58
49
  }
59
50
  //# sourceMappingURL=plugin-handle-ipns-record.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-handle-ipns-record.js","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-ipns-record.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin-handle-ipns-record.js","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-ipns-record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AACxC,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AACrF,OAAO,EAAE,6BAA6B,EAAE,MAAM,8CAA8C,CAAA;AAC5F,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAI7C;;;GAGG;AACH,MAAM,OAAO,gBAAiB,SAAQ,UAAU;IACrC,EAAE,GAAG,oBAAoB,CAAA;IACzB,KAAK,GAAG,EAAE,CAAA;IAEnB,SAAS,CAAE,EAAE,MAAM,EAAiB;QAClC,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,KAAK,sBAAsB,CAAC,CAAA;IACvF,CAAC;IAED,KAAK,CAAC,MAAM,CAAE,OAAsE;QAClF,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,CAAA;QACjD,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC,aAAa,CAAA;QAE3C,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,EAAE,IAAI,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YAC9E,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,kDAAkD,EAAE,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAA;YACrF,OAAO,kBAAkB,CAAC,QAAQ,EAAE,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAA;QACrE,CAAC;QAED,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,OAAO,kBAAkB,CAAC,QAAQ,EAAE,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAA;QACrG,CAAC;QAED,IAAI,MAAc,CAAA;QAElB,IAAI,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAA;YACjE,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACzC,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,0CAA0C,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAA;YAEzE,OAAO,kBAAkB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;QAC1C,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC1D,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QAE9C,OAAO,UAAU,CAAC,QAAQ,EAAE,KAAK,EAAE;YACjC,OAAO,EAAE;gBACP,gBAAgB,EAAE,GAAG,KAAK,CAAC,UAAU,EAAE;gBACvC,cAAc,EAAE,iBAAiB,CAAC,SAAS;gBAC3C,qBAAqB,EAAE,eACrB,6BAA6B,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,MAAM,GAAG,iBAAiB,CAAC,SAAS,EAAE,CAC7G,EAAE;gBACF,cAAc,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;gBAC5C,eAAe,EAAE,mBAAmB,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE;gBACrF,eAAe,EAAE,MAAM;aACxB;SACF,CAAC,CAAA;IACJ,CAAC;CACF"}
@@ -1,5 +1,5 @@
1
1
  import { BasePlugin } from './plugin-base.js';
2
- import type { PluginContext } from './types.js';
2
+ import type { PluginContext } from '../index.js';
3
3
  /**
4
4
  * Accepts a UnixFS `CID` and returns a `.tar` file containing the file or
5
5
  * directory structure referenced by the `CID`.
@@ -7,7 +7,7 @@ import type { PluginContext } from './types.js';
7
7
  export declare class TarPlugin extends BasePlugin {
8
8
  readonly id = "tar-plugin";
9
9
  readonly codes: never[];
10
- canHandle({ cid, accept, query, byteRangeContext }: PluginContext): boolean;
11
- handle(context: PluginContext & Required<Pick<PluginContext, 'byteRangeContext'>>): Promise<Response>;
10
+ canHandle({ accept }: PluginContext): boolean;
11
+ handle(context: PluginContext): Promise<Response>;
12
12
  }
13
13
  //# sourceMappingURL=plugin-handle-tar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-handle-tar.d.ts","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-tar.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;;GAGG;AACH,qBAAa,SAAU,SAAQ,UAAU;IACvC,QAAQ,CAAC,EAAE,gBAAe;IAC1B,QAAQ,CAAC,KAAK,UAAK;IAEnB,SAAS,CAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,aAAa,GAAG,OAAO;IAQtE,MAAM,CAAE,OAAO,EAAE,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC;CAyB7G"}
1
+ {"version":3,"file":"plugin-handle-tar.d.ts","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-tar.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD;;;GAGG;AACH,qBAAa,SAAU,SAAQ,UAAU;IACvC,QAAQ,CAAC,EAAE,gBAAe;IAC1B,QAAQ,CAAC,KAAK,UAAK;IAEnB,SAAS,CAAE,EAAE,MAAM,EAAE,EAAE,aAAa,GAAG,OAAO;IAIxC,MAAM,CAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC;CAuBzD"}
@@ -1,9 +1,11 @@
1
+ import { NotUnixFSError } from '@helia/unixfs/errors';
1
2
  import { code as dagPbCode } from '@ipld/dag-pb';
2
3
  import toBrowserReadableStream from 'it-to-browser-readablestream';
3
4
  import { code as rawCode } from 'multiformats/codecs/raw';
4
- import { getETag } from '../utils/get-e-tag.js';
5
+ import { MEDIA_TYPE_TAR } from "../utils/content-types.js";
6
+ import { getContentDispositionFilename } from "../utils/get-content-disposition-filename.js";
5
7
  import { tarStream } from '../utils/get-tar-stream.js';
6
- import { notAcceptableResponse, okRangeResponse } from '../utils/responses.js';
8
+ import { badRequestResponse, okResponse } from '../utils/responses.js';
7
9
  import { BasePlugin } from './plugin-base.js';
8
10
  /**
9
11
  * Accepts a UnixFS `CID` and returns a `.tar` file containing the file or
@@ -12,29 +14,25 @@ import { BasePlugin } from './plugin-base.js';
12
14
  export class TarPlugin extends BasePlugin {
13
15
  id = 'tar-plugin';
14
16
  codes = [];
15
- canHandle({ cid, accept, query, byteRangeContext }) {
16
- if (byteRangeContext == null) {
17
- return false;
18
- }
19
- return accept?.mimeType === 'application/x-tar' || query.format === 'tar';
17
+ canHandle({ accept }) {
18
+ return accept.some(header => header.contentType.mediaType === MEDIA_TYPE_TAR);
20
19
  }
21
20
  async handle(context) {
22
- const { cid, path, resource, options, pathDetails } = context;
23
- const { getBlockstore } = this.pluginOptions;
24
- const terminusElement = pathDetails?.terminalElement.cid ?? cid;
25
- if (terminusElement.code !== dagPbCode && terminusElement.code !== rawCode) {
26
- return notAcceptableResponse('only UnixFS data can be returned in a TAR file');
21
+ const { terminalElement, url, resource, options, blockstore, range } = context;
22
+ if (terminalElement.cid.code !== dagPbCode && terminalElement.cid.code !== rawCode) {
23
+ return badRequestResponse(resource, new NotUnixFSError('Only UnixFS data can be returned in a TAR file'));
24
+ }
25
+ if (range != null) {
26
+ return badRequestResponse(resource, new Error('Range requests are not supported for TAR files'));
27
27
  }
28
- context.reqFormat = 'tar';
29
- context.query.download = true;
30
- context.query.filename = context.query.filename ?? `${terminusElement.toString()}.tar`;
31
- const blockstore = getBlockstore(terminusElement, resource, options?.session, options);
32
- const stream = toBrowserReadableStream(tarStream(`/ipfs/${cid}/${path}`, blockstore, options));
33
- context.byteRangeContext.setBody(stream);
34
- const response = okRangeResponse(resource, context.byteRangeContext.getBody('application/x-tar'), { byteRangeContext: context.byteRangeContext, log: this.log });
35
- response.headers.set('content-type', context.byteRangeContext.getContentType() ?? 'application/x-tar');
36
- response.headers.set('etag', getETag({ cid: terminusElement, reqFormat: context.reqFormat, weak: true }));
37
- return response;
28
+ const stream = toBrowserReadableStream(tarStream(`/ipfs/${terminalElement.cid}${url.pathname}`, blockstore, options));
29
+ return okResponse(resource, stream, {
30
+ headers: {
31
+ 'content-type': MEDIA_TYPE_TAR,
32
+ 'content-disposition': `attachment; ${getContentDispositionFilename(url.searchParams.get('filename') ?? `${terminalElement.cid.toString()}.tar`)}`,
33
+ 'accept-ranges': 'none'
34
+ }
35
+ });
38
36
  }
39
37
  }
40
38
  //# sourceMappingURL=plugin-handle-tar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-handle-tar.js","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-tar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,uBAAuB,MAAM,8BAA8B,CAAA;AAClE,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAG7C;;;GAGG;AACH,MAAM,OAAO,SAAU,SAAQ,UAAU;IAC9B,EAAE,GAAG,YAAY,CAAA;IACjB,KAAK,GAAG,EAAE,CAAA;IAEnB,SAAS,CAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAiB;QAChE,IAAI,gBAAgB,IAAI,IAAI,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAA;QACd,CAAC;QAED,OAAO,MAAM,EAAE,QAAQ,KAAK,mBAAmB,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAA;IAC3E,CAAC;IAED,KAAK,CAAC,MAAM,CAAE,OAA0E;QACtF,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAA;QAC7D,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,aAAa,CAAA;QAE5C,MAAM,eAAe,GAAG,WAAW,EAAE,eAAe,CAAC,GAAG,IAAI,GAAG,CAAA;QAC/D,IAAI,eAAe,CAAC,IAAI,KAAK,SAAS,IAAI,eAAe,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3E,OAAO,qBAAqB,CAAC,gDAAgD,CAAC,CAAA;QAChF,CAAC;QAED,OAAO,CAAC,SAAS,GAAG,KAAK,CAAA;QACzB,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAA;QAC7B,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,IAAI,GAAG,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAA;QAEtF,MAAM,UAAU,GAAG,aAAa,CAAC,eAAe,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;QACtF,MAAM,MAAM,GAAG,uBAAuB,CAAa,SAAS,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAA;QAE1G,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAExC,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,EAAE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;QAChK,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,gBAAgB,CAAC,cAAc,EAAE,IAAI,mBAAmB,CAAC,CAAA;QAEtG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QAEzG,OAAO,QAAQ,CAAA;IACjB,CAAC;CACF"}
1
+ {"version":3,"file":"plugin-handle-tar.js","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-tar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,uBAAuB,MAAM,8BAA8B,CAAA;AAClE,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,6BAA6B,EAAE,MAAM,8CAA8C,CAAA;AAC5F,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAG7C;;;GAGG;AACH,MAAM,OAAO,SAAU,SAAQ,UAAU;IAC9B,EAAE,GAAG,YAAY,CAAA;IACjB,KAAK,GAAG,EAAE,CAAA;IAEnB,SAAS,CAAE,EAAE,MAAM,EAAiB;QAClC,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,KAAK,cAAc,CAAC,CAAA;IAC/E,CAAC;IAED,KAAK,CAAC,MAAM,CAAE,OAAsB;QAClC,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,OAAO,CAAA;QAE9E,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACnF,OAAO,kBAAkB,CAAC,QAAQ,EAAE,IAAI,cAAc,CAAC,gDAAgD,CAAC,CAAC,CAAA;QAC3G,CAAC;QAED,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,OAAO,kBAAkB,CAAC,QAAQ,EAAE,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC,CAAA;QAClG,CAAC;QAED,MAAM,MAAM,GAAG,uBAAuB,CAAa,SAAS,CAAC,SAAS,eAAe,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAA;QAEjI,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE;YAClC,OAAO,EAAE;gBACP,cAAc,EAAE,cAAc;gBAC9B,qBAAqB,EAAE,eACrB,6BAA6B,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,eAAe,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAC3G,EAAE;gBACF,eAAe,EAAE,MAAM;aACxB;SACF,CAAC,CAAA;IACJ,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ import { BasePlugin } from './plugin-base.js';
2
+ import type { PluginContext } from '../index.js';
3
+ /**
4
+ * Handles UnixFS content
5
+ */
6
+ export declare class UnixFSPlugin extends BasePlugin {
7
+ readonly id = "unixfs-plugin";
8
+ readonly codes: number[];
9
+ canHandle({ terminalElement, accept }: PluginContext): boolean;
10
+ handle(context: PluginContext): Promise<Response>;
11
+ private streamFile;
12
+ private detectContentType;
13
+ }
14
+ //# sourceMappingURL=plugin-handle-unixfs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-handle-unixfs.d.ts","sourceRoot":"","sources":["../../../src/plugins/plugin-handle-unixfs.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AA4BhD;;GAEG;AACH,qBAAa,YAAa,SAAQ,UAAU;IAC1C,QAAQ,CAAC,EAAE,mBAAkB;IAC7B,QAAQ,CAAC,KAAK,WAAwB;IAEtC,SAAS,CAAE,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,aAAa,GAAG,OAAO;IASzD,MAAM,CAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC;YA+E1C,UAAU;YA6CV,iBAAiB;CAqChC"}