@helia/verified-fetch 4.0.2 → 4.0.4
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/dist/index.min.js +69 -63
- package/dist/index.min.js.map +4 -4
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +1 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/plugins/plugin-handle-cbor.d.ts +17 -0
- package/dist/src/plugins/plugin-handle-cbor.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-cbor.js +94 -0
- package/dist/src/plugins/plugin-handle-cbor.js.map +1 -0
- package/dist/src/plugins/plugin-handle-dag-cbor.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-cbor.js +16 -27
- package/dist/src/plugins/plugin-handle-dag-cbor.js.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-pb.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-pb.js +14 -2
- 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 +52 -7
- package/dist/src/plugins/plugin-handle-dag-walk.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 -3
- package/dist/src/plugins/plugin-handle-json.js.map +1 -1
- package/dist/src/utils/byte-range-context.js +1 -1
- package/dist/src/utils/byte-range-context.js.map +1 -1
- package/dist/src/utils/dag-cbor-to-safe-json.d.ts +8 -0
- package/dist/src/utils/dag-cbor-to-safe-json.d.ts.map +1 -1
- package/dist/src/utils/dag-cbor-to-safe-json.js +46 -17
- package/dist/src/utils/dag-cbor-to-safe-json.js.map +1 -1
- package/dist/src/utils/get-content-type.js +2 -2
- package/dist/src/utils/get-content-type.js.map +1 -1
- package/dist/src/utils/select-output-type.d.ts.map +1 -1
- package/dist/src/utils/select-output-type.js +13 -1
- package/dist/src/utils/select-output-type.js.map +1 -1
- package/dist/src/verified-fetch.d.ts.map +1 -1
- package/dist/src/verified-fetch.js +4 -2
- package/dist/src/verified-fetch.js.map +1 -1
- package/package.json +4 -4
- package/src/constants.ts +1 -0
- package/src/plugins/plugin-handle-cbor.ts +107 -0
- package/src/plugins/plugin-handle-dag-cbor.ts +17 -27
- package/src/plugins/plugin-handle-dag-pb.ts +16 -2
- package/src/plugins/plugin-handle-dag-walk.ts +56 -7
- package/src/plugins/plugin-handle-json.ts +5 -3
- package/src/utils/byte-range-context.ts +1 -1
- package/src/utils/dag-cbor-to-safe-json.ts +55 -19
- package/src/utils/get-content-type.ts +2 -2
- package/src/utils/select-output-type.ts +13 -1
- package/src/verified-fetch.ts +4 -2
|
@@ -2,6 +2,7 @@ import * as ipldDagCbor from '@ipld/dag-cbor'
|
|
|
2
2
|
import * as ipldDagJson from '@ipld/dag-json'
|
|
3
3
|
import toBuffer from 'it-to-buffer'
|
|
4
4
|
import { code as jsonCode } from 'multiformats/codecs/json'
|
|
5
|
+
import { CODEC_CBOR } from '../constants.ts'
|
|
5
6
|
import { notAcceptableResponse, okRangeResponse } from '../utils/responses.js'
|
|
6
7
|
import { BasePlugin } from './plugin-base.js'
|
|
7
8
|
import type { PluginContext } from './types.js'
|
|
@@ -18,8 +19,9 @@ export class JsonPlugin extends BasePlugin {
|
|
|
18
19
|
return false
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
if (accept?.mimeType === 'application/vnd.ipld.dag-json' && cid.code !== ipldDagCbor.code) {
|
|
22
|
-
// we can handle application/vnd.ipld.dag-json, but if the CID codec is
|
|
22
|
+
if (accept?.mimeType === 'application/vnd.ipld.dag-json' && cid.code !== ipldDagCbor.code && cid.code !== CODEC_CBOR) {
|
|
23
|
+
// we can handle application/vnd.ipld.dag-json, but if the CID codec is
|
|
24
|
+
// cbor related, cbor related plugins will handle it
|
|
23
25
|
// TODO: remove the need for deny-listing cases in plugins
|
|
24
26
|
return true
|
|
25
27
|
}
|
|
@@ -47,7 +49,7 @@ export class JsonPlugin extends BasePlugin {
|
|
|
47
49
|
const obj = ipldDagJson.decode(block)
|
|
48
50
|
body = ipldDagCbor.encode(obj)
|
|
49
51
|
} catch (err) {
|
|
50
|
-
this.log.error('could not transform %c to application/vnd.ipld.dag-cbor', err)
|
|
52
|
+
this.log.error('could not transform %c to application/vnd.ipld.dag-cbor - %e', err)
|
|
51
53
|
return notAcceptableResponse(resource)
|
|
52
54
|
}
|
|
53
55
|
} else {
|
|
@@ -1,5 +1,27 @@
|
|
|
1
|
-
import { decode } from 'cborg'
|
|
2
|
-
import { encode } from 'cborg/json'
|
|
1
|
+
import { decode, encode } from 'cborg'
|
|
2
|
+
import { encode as jsonEncode } from 'cborg/json'
|
|
3
|
+
import { CID } from 'multiformats/cid'
|
|
4
|
+
import type { DecodeOptions } from 'cborg'
|
|
5
|
+
|
|
6
|
+
// https://github.com/ipfs/go-ipfs/issues/3570#issuecomment-273931692
|
|
7
|
+
const CID_CBOR_TAG = 42
|
|
8
|
+
|
|
9
|
+
const options: DecodeOptions = {
|
|
10
|
+
allowIndefinite: false,
|
|
11
|
+
coerceUndefinedToNull: false,
|
|
12
|
+
allowNaN: false,
|
|
13
|
+
allowInfinity: false,
|
|
14
|
+
strict: true,
|
|
15
|
+
useMaps: false,
|
|
16
|
+
rejectDuplicateMapKeys: true,
|
|
17
|
+
tags: [],
|
|
18
|
+
|
|
19
|
+
// this is different to `DAG-CBOR` - the reason we disallow BigInts is
|
|
20
|
+
// because we are about to re-encode to `JSON` which does not support
|
|
21
|
+
// BigInts. Blocks containing large numbers should be deserialized using a
|
|
22
|
+
// cbor decoder instead
|
|
23
|
+
allowBigInt: false.valueOf
|
|
24
|
+
}
|
|
3
25
|
|
|
4
26
|
/**
|
|
5
27
|
* Take a `DAG-CBOR` encoded `Uint8Array`, deserialize it as an object and
|
|
@@ -7,21 +29,35 @@ import { encode } from 'cborg/json'
|
|
|
7
29
|
* `JSON.parse` without losing any data.
|
|
8
30
|
*/
|
|
9
31
|
export function dagCborToSafeJSON (buf: Uint8Array): string {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return new TextDecoder().decode(
|
|
32
|
+
const opts: DecodeOptions = {
|
|
33
|
+
...options,
|
|
34
|
+
tags: []
|
|
35
|
+
}
|
|
36
|
+
opts.tags[CID_CBOR_TAG] = (bytes: Uint8Array): any => {
|
|
37
|
+
if (bytes[0] !== 0) {
|
|
38
|
+
throw new Error('Invalid CID for CBOR tag 42; expected leading 0x00')
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
'/': CID.decode(bytes.subarray(1)).toString() // ignore leading 0x00
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const obj = decode(buf, opts)
|
|
47
|
+
|
|
48
|
+
return new TextDecoder().decode(jsonEncode(obj))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Decode CBOR to object without CID tag support
|
|
53
|
+
*/
|
|
54
|
+
export function cborToObject (buf: Uint8Array): any {
|
|
55
|
+
return decode(buf, options)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Decode CBOR to object without CID tag support
|
|
60
|
+
*/
|
|
61
|
+
export function objectToCbor (obj: any): Uint8Array {
|
|
62
|
+
return encode(obj, options)
|
|
27
63
|
}
|
|
@@ -41,9 +41,9 @@ export async function getContentType ({ bytes, path, contentTypeParser, log, def
|
|
|
41
41
|
} else if (parsed != null) {
|
|
42
42
|
contentType = parsed
|
|
43
43
|
}
|
|
44
|
-
log.trace('contentTypeParser returned %s', contentType)
|
|
44
|
+
log.trace('contentTypeParser returned %s for file with name %s', contentType, fileName)
|
|
45
45
|
} catch (err) {
|
|
46
|
-
log.error('error parsing content type', err)
|
|
46
|
+
log.error('error parsing content type - %e', err)
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -3,6 +3,7 @@ import { code as dagJsonCode } from '@ipld/dag-json'
|
|
|
3
3
|
import { code as dagPbCode } from '@ipld/dag-pb'
|
|
4
4
|
import { code as jsonCode } from 'multiformats/codecs/json'
|
|
5
5
|
import { code as rawCode } from 'multiformats/codecs/raw'
|
|
6
|
+
import { CODEC_CBOR } from '../constants.ts'
|
|
6
7
|
import type { RequestFormatShorthand } from '../index.js'
|
|
7
8
|
import type { CID } from 'multiformats/cid'
|
|
8
9
|
|
|
@@ -59,6 +60,17 @@ const CID_TYPE_MAP: Record<number, string[]> = {
|
|
|
59
60
|
'application/vnd.ipld.dag-json',
|
|
60
61
|
'application/vnd.ipld.car',
|
|
61
62
|
'application/x-tar'
|
|
63
|
+
],
|
|
64
|
+
[CODEC_CBOR]: [
|
|
65
|
+
'application/json',
|
|
66
|
+
'application/vnd.ipld.dag-cbor',
|
|
67
|
+
'application/cbor',
|
|
68
|
+
'application/vnd.ipld.dag-json',
|
|
69
|
+
'application/octet-stream',
|
|
70
|
+
'application/vnd.ipld.raw',
|
|
71
|
+
'application/vnd.ipfs.ipns-record',
|
|
72
|
+
'application/vnd.ipld.car',
|
|
73
|
+
'text/html'
|
|
62
74
|
]
|
|
63
75
|
}
|
|
64
76
|
|
|
@@ -71,7 +83,7 @@ export interface AcceptHeader {
|
|
|
71
83
|
* Selects an output mime-type based on the CID and a passed `Accept` header
|
|
72
84
|
*/
|
|
73
85
|
export function selectOutputType (cid: CID, accept?: string): AcceptHeader | undefined {
|
|
74
|
-
const cidMimeTypes = CID_TYPE_MAP[cid.code]
|
|
86
|
+
const cidMimeTypes = CID_TYPE_MAP[cid.code] ?? []
|
|
75
87
|
|
|
76
88
|
if (accept != null) {
|
|
77
89
|
return chooseMimeType(accept, cidMimeTypes)
|
package/src/verified-fetch.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { CustomProgressEvent } from 'progress-events'
|
|
|
5
5
|
import QuickLRU from 'quick-lru'
|
|
6
6
|
import { ByteRangeContextPlugin } from './plugins/plugin-handle-byte-range-context.js'
|
|
7
7
|
import { CarPlugin } from './plugins/plugin-handle-car.js'
|
|
8
|
+
import { CborPlugin } from './plugins/plugin-handle-cbor.js'
|
|
8
9
|
import { DagCborPlugin } from './plugins/plugin-handle-dag-cbor.js'
|
|
9
10
|
import { DagPbPlugin } from './plugins/plugin-handle-dag-pb.js'
|
|
10
11
|
import { DagWalkPlugin } from './plugins/plugin-handle-dag-walk.js'
|
|
@@ -99,7 +100,8 @@ export class VerifiedFetch {
|
|
|
99
100
|
new TarPlugin(pluginOptions),
|
|
100
101
|
new JsonPlugin(pluginOptions),
|
|
101
102
|
new DagCborPlugin(pluginOptions),
|
|
102
|
-
new DagPbPlugin(pluginOptions)
|
|
103
|
+
new DagPbPlugin(pluginOptions),
|
|
104
|
+
new CborPlugin(pluginOptions)
|
|
103
105
|
]
|
|
104
106
|
|
|
105
107
|
const customPlugins = init.plugins?.map((pluginFactory) => pluginFactory(pluginOptions)) ?? []
|
|
@@ -245,7 +247,7 @@ export class VerifiedFetch {
|
|
|
245
247
|
this.log(`starting pipeline pass #${passCount + 1}`)
|
|
246
248
|
passCount++
|
|
247
249
|
|
|
248
|
-
this.log.trace('checking which plugins can handle %c%s with accept %o', context.cid, context.path
|
|
250
|
+
this.log.trace('checking which plugins can handle %c%s with accept %o', context.cid, context.path.length > 0 ? `/${context.path.join('/')}` : '', context.accept)
|
|
249
251
|
|
|
250
252
|
// gather plugins that say they can handle the *current* context, but haven't been used yet
|
|
251
253
|
const readyPlugins = this.plugins.filter(p => !pluginsUsed.has(p.id)).filter(p => p.canHandle(context))
|