@helia/verified-fetch 4.1.1 → 5.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 +6 -40
- package/dist/index.min.js +73 -534
- package/dist/index.min.js.map +4 -4
- package/dist/src/constants.d.ts +2 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +2 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/index.d.ts +162 -68
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -40
- package/dist/src/index.js.map +1 -1
- package/dist/src/plugins/index.d.ts +0 -5
- package/dist/src/plugins/index.d.ts.map +1 -1
- package/dist/src/plugins/index.js +0 -4
- package/dist/src/plugins/index.js.map +1 -1
- package/dist/src/plugins/plugin-base.d.ts +8 -9
- package/dist/src/plugins/plugin-base.d.ts.map +1 -1
- package/dist/src/plugins/plugin-base.js +5 -6
- package/dist/src/plugins/plugin-base.js.map +1 -1
- package/dist/src/plugins/plugin-handle-car.d.ts +3 -3
- package/dist/src/plugins/plugin-handle-car.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-car.js +38 -39
- package/dist/src/plugins/plugin-handle-car.js.map +1 -1
- package/dist/src/plugins/plugin-handle-ipld.d.ts +12 -0
- package/dist/src/plugins/plugin-handle-ipld.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-ipld.js +83 -0
- package/dist/src/plugins/plugin-handle-ipld.js.map +1 -0
- package/dist/src/plugins/plugin-handle-ipns-record.d.ts +3 -3
- package/dist/src/plugins/plugin-handle-ipns-record.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-ipns-record.js +25 -34
- package/dist/src/plugins/plugin-handle-ipns-record.js.map +1 -1
- package/dist/src/plugins/plugin-handle-tar.d.ts +3 -3
- package/dist/src/plugins/plugin-handle-tar.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-tar.js +20 -22
- package/dist/src/plugins/plugin-handle-tar.js.map +1 -1
- package/dist/src/plugins/plugin-handle-unixfs.d.ts +14 -0
- package/dist/src/plugins/plugin-handle-unixfs.d.ts.map +1 -0
- package/dist/src/plugins/plugin-handle-unixfs.js +180 -0
- package/dist/src/plugins/plugin-handle-unixfs.js.map +1 -0
- package/dist/src/plugins/types.d.ts +1 -77
- package/dist/src/plugins/types.d.ts.map +1 -1
- package/dist/src/url-resolver.d.ts +29 -11
- package/dist/src/url-resolver.d.ts.map +1 -1
- package/dist/src/url-resolver.js +152 -74
- package/dist/src/url-resolver.js.map +1 -1
- package/dist/src/utils/content-type-parser.d.ts.map +1 -1
- package/dist/src/utils/content-type-parser.js +4 -3
- package/dist/src/utils/content-type-parser.js.map +1 -1
- package/dist/src/utils/content-types.d.ts +26 -0
- package/dist/src/utils/content-types.d.ts.map +1 -0
- package/dist/src/utils/content-types.js +137 -0
- package/dist/src/utils/content-types.js.map +1 -0
- package/dist/src/utils/convert-output.d.ts +17 -0
- package/dist/src/utils/convert-output.d.ts.map +1 -0
- package/dist/src/utils/convert-output.js +176 -0
- package/dist/src/utils/convert-output.js.map +1 -0
- package/dist/src/utils/error-to-response.d.ts +3 -0
- package/dist/src/utils/error-to-response.d.ts.map +1 -0
- package/dist/src/utils/error-to-response.js +40 -0
- package/dist/src/utils/error-to-response.js.map +1 -0
- package/dist/src/utils/get-content-disposition-filename.d.ts +1 -1
- package/dist/src/utils/get-content-disposition-filename.d.ts.map +1 -1
- package/dist/src/utils/get-content-disposition-filename.js +4 -0
- package/dist/src/utils/get-content-disposition-filename.js.map +1 -1
- package/dist/src/utils/get-e-tag.d.ts +20 -15
- package/dist/src/utils/get-e-tag.d.ts.map +1 -1
- package/dist/src/utils/get-e-tag.js +8 -22
- package/dist/src/utils/get-e-tag.js.map +1 -1
- package/dist/src/utils/get-offset-and-length.d.ts +12 -2
- package/dist/src/utils/get-offset-and-length.d.ts.map +1 -1
- package/dist/src/utils/get-offset-and-length.js +63 -21
- package/dist/src/utils/get-offset-and-length.js.map +1 -1
- package/dist/src/utils/get-range-header.d.ts +22 -0
- package/dist/src/utils/get-range-header.d.ts.map +1 -0
- package/dist/src/utils/get-range-header.js +69 -0
- package/dist/src/utils/get-range-header.js.map +1 -0
- package/dist/src/utils/parse-url-string.d.ts +2 -1
- package/dist/src/utils/parse-url-string.d.ts.map +1 -1
- package/dist/src/utils/parse-url-string.js +46 -71
- package/dist/src/utils/parse-url-string.js.map +1 -1
- package/dist/src/utils/resource-to-cache-key.d.ts +3 -3
- package/dist/src/utils/resource-to-cache-key.js +5 -5
- package/dist/src/utils/resource-to-cache-key.js.map +1 -1
- package/dist/src/utils/response-headers.d.ts +4 -14
- package/dist/src/utils/response-headers.d.ts.map +1 -1
- package/dist/src/utils/response-headers.js +36 -36
- package/dist/src/utils/response-headers.js.map +1 -1
- package/dist/src/utils/responses.d.ts +30 -11
- package/dist/src/utils/responses.d.ts.map +1 -1
- package/dist/src/utils/responses.js +146 -39
- package/dist/src/utils/responses.js.map +1 -1
- package/dist/src/verified-fetch.d.ts +16 -15
- package/dist/src/verified-fetch.d.ts.map +1 -1
- package/dist/src/verified-fetch.js +302 -238
- package/dist/src/verified-fetch.js.map +1 -1
- package/dist/typedoc-urls.json +64 -45
- package/package.json +4 -3
- package/src/constants.ts +3 -0
- package/src/index.ts +199 -68
- package/src/plugins/index.ts +0 -6
- package/src/plugins/plugin-base.ts +8 -10
- package/src/plugins/plugin-handle-car.ts +48 -46
- package/src/plugins/plugin-handle-ipld.ts +93 -0
- package/src/plugins/plugin-handle-ipns-record.ts +31 -41
- package/src/plugins/plugin-handle-tar.ts +25 -29
- package/src/plugins/plugin-handle-unixfs.ts +217 -0
- package/src/plugins/types.ts +0 -86
- package/src/url-resolver.ts +197 -83
- package/src/utils/content-type-parser.ts +4 -3
- package/src/utils/content-types.ts +159 -0
- package/src/utils/convert-output.ts +187 -0
- package/src/utils/error-to-response.ts +49 -0
- package/src/utils/get-content-disposition-filename.ts +7 -1
- package/src/utils/get-e-tag.ts +26 -35
- package/src/utils/get-offset-and-length.ts +75 -21
- package/src/utils/get-range-header.ts +107 -0
- package/src/utils/parse-url-string.ts +51 -80
- package/src/utils/resource-to-cache-key.ts +5 -5
- package/src/utils/response-headers.ts +40 -41
- package/src/utils/responses.ts +186 -45
- package/src/verified-fetch.ts +353 -270
- package/dist/src/plugins/plugin-handle-byte-range-context.d.ts +0 -14
- package/dist/src/plugins/plugin-handle-byte-range-context.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-byte-range-context.js +0 -25
- package/dist/src/plugins/plugin-handle-byte-range-context.js.map +0 -1
- package/dist/src/plugins/plugin-handle-cbor.d.ts +0 -17
- package/dist/src/plugins/plugin-handle-cbor.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-cbor.js +0 -94
- package/dist/src/plugins/plugin-handle-cbor.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.d.ts +0 -27
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.js +0 -279
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-cbor.d.ts +0 -17
- package/dist/src/plugins/plugin-handle-dag-cbor.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-cbor.js +0 -66
- package/dist/src/plugins/plugin-handle-dag-cbor.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-pb.d.ts +0 -17
- package/dist/src/plugins/plugin-handle-dag-pb.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-pb.js +0 -209
- package/dist/src/plugins/plugin-handle-dag-pb.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-walk.d.ts +0 -21
- package/dist/src/plugins/plugin-handle-dag-walk.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dag-walk.js +0 -95
- package/dist/src/plugins/plugin-handle-dag-walk.js.map +0 -1
- package/dist/src/plugins/plugin-handle-dir-index-html.d.ts +0 -10
- package/dist/src/plugins/plugin-handle-dir-index-html.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-dir-index-html.js +0 -59
- package/dist/src/plugins/plugin-handle-dir-index-html.js.map +0 -1
- package/dist/src/plugins/plugin-handle-json.d.ts +0 -12
- package/dist/src/plugins/plugin-handle-json.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-json.js +0 -73
- package/dist/src/plugins/plugin-handle-json.js.map +0 -1
- package/dist/src/plugins/plugin-handle-raw.d.ts +0 -9
- package/dist/src/plugins/plugin-handle-raw.d.ts.map +0 -1
- package/dist/src/plugins/plugin-handle-raw.js +0 -92
- package/dist/src/plugins/plugin-handle-raw.js.map +0 -1
- package/dist/src/plugins/plugins.d.ts +0 -6
- package/dist/src/plugins/plugins.d.ts.map +0 -1
- package/dist/src/plugins/plugins.js +0 -6
- package/dist/src/plugins/plugins.js.map +0 -1
- package/dist/src/utils/byte-range-context.d.ts +0 -103
- package/dist/src/utils/byte-range-context.d.ts.map +0 -1
- package/dist/src/utils/byte-range-context.js +0 -504
- package/dist/src/utils/byte-range-context.js.map +0 -1
- package/dist/src/utils/dag-cbor-to-safe-json.d.ts +0 -15
- package/dist/src/utils/dag-cbor-to-safe-json.d.ts.map +0 -1
- package/dist/src/utils/dag-cbor-to-safe-json.js +0 -54
- package/dist/src/utils/dag-cbor-to-safe-json.js.map +0 -1
- package/dist/src/utils/dir-index-html.d.ts +0 -19
- package/dist/src/utils/dir-index-html.d.ts.map +0 -1
- package/dist/src/utils/dir-index-html.js +0 -438
- package/dist/src/utils/dir-index-html.js.map +0 -1
- package/dist/src/utils/get-peer-id-from-string.d.ts +0 -3
- package/dist/src/utils/get-peer-id-from-string.d.ts.map +0 -1
- package/dist/src/utils/get-peer-id-from-string.js +0 -10
- package/dist/src/utils/get-peer-id-from-string.js.map +0 -1
- package/dist/src/utils/get-resolved-accept-header.d.ts +0 -9
- package/dist/src/utils/get-resolved-accept-header.d.ts.map +0 -1
- package/dist/src/utils/get-resolved-accept-header.js +0 -27
- package/dist/src/utils/get-resolved-accept-header.js.map +0 -1
- package/dist/src/utils/get-stream-from-async-iterable.d.ts +0 -9
- package/dist/src/utils/get-stream-from-async-iterable.d.ts.map +0 -1
- package/dist/src/utils/get-stream-from-async-iterable.js +0 -43
- package/dist/src/utils/get-stream-from-async-iterable.js.map +0 -1
- package/dist/src/utils/handle-redirects.d.ts +0 -16
- package/dist/src/utils/handle-redirects.d.ts.map +0 -1
- package/dist/src/utils/handle-redirects.js +0 -84
- package/dist/src/utils/handle-redirects.js.map +0 -1
- package/dist/src/utils/is-accept-explicit.d.ts +0 -15
- package/dist/src/utils/is-accept-explicit.d.ts.map +0 -1
- package/dist/src/utils/is-accept-explicit.js +0 -26
- package/dist/src/utils/is-accept-explicit.js.map +0 -1
- package/dist/src/utils/request-headers.d.ts +0 -13
- package/dist/src/utils/request-headers.d.ts.map +0 -1
- package/dist/src/utils/request-headers.js +0 -63
- package/dist/src/utils/request-headers.js.map +0 -1
- package/dist/src/utils/select-output-type.d.ts +0 -17
- package/dist/src/utils/select-output-type.d.ts.map +0 -1
- package/dist/src/utils/select-output-type.js +0 -153
- package/dist/src/utils/select-output-type.js.map +0 -1
- package/dist/src/utils/tlru.d.ts +0 -15
- package/dist/src/utils/tlru.d.ts.map +0 -1
- package/dist/src/utils/tlru.js +0 -34
- package/dist/src/utils/tlru.js.map +0 -1
- package/dist/src/utils/walk-path.d.ts +0 -27
- package/dist/src/utils/walk-path.d.ts.map +0 -1
- package/dist/src/utils/walk-path.js +0 -45
- package/dist/src/utils/walk-path.js.map +0 -1
- package/src/plugins/plugin-handle-byte-range-context.ts +0 -30
- package/src/plugins/plugin-handle-cbor.ts +0 -107
- package/src/plugins/plugin-handle-dag-cbor-html-preview.ts +0 -295
- package/src/plugins/plugin-handle-dag-cbor.ts +0 -83
- package/src/plugins/plugin-handle-dag-pb.ts +0 -248
- package/src/plugins/plugin-handle-dag-walk.ts +0 -110
- package/src/plugins/plugin-handle-dir-index-html.ts +0 -72
- package/src/plugins/plugin-handle-json.ts +0 -80
- package/src/plugins/plugin-handle-raw.ts +0 -110
- package/src/plugins/plugins.ts +0 -5
- package/src/utils/byte-range-context.ts +0 -597
- package/src/utils/dag-cbor-to-safe-json.ts +0 -63
- package/src/utils/dir-index-html.ts +0 -505
- package/src/utils/get-peer-id-from-string.ts +0 -12
- package/src/utils/get-resolved-accept-header.ts +0 -42
- package/src/utils/get-stream-from-async-iterable.ts +0 -49
- package/src/utils/handle-redirects.ts +0 -109
- package/src/utils/is-accept-explicit.ts +0 -38
- package/src/utils/request-headers.ts +0 -65
- package/src/utils/select-output-type.ts +0 -175
- package/src/utils/tlru.ts +0 -42
- package/src/utils/walk-path.ts +0 -69
|
@@ -1,30 +1,16 @@
|
|
|
1
|
-
const getPrefix = ({ weak, reqFormat }) => {
|
|
2
|
-
if (reqFormat === 'tar' || reqFormat === 'car' || reqFormat === 'ipns-record' || weak === true) {
|
|
3
|
-
return 'W/';
|
|
4
|
-
}
|
|
5
|
-
return '';
|
|
6
|
-
};
|
|
7
|
-
const getFormatSuffix = ({ reqFormat }) => {
|
|
8
|
-
if (reqFormat == null) {
|
|
9
|
-
return '';
|
|
10
|
-
}
|
|
11
|
-
if (reqFormat === 'tar') {
|
|
12
|
-
return '.x-tar';
|
|
13
|
-
}
|
|
14
|
-
return `.${reqFormat}`;
|
|
15
|
-
};
|
|
16
1
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
2
|
+
* We use strong Etags for immutable responses and weak ones (prefixed with W/ )
|
|
3
|
+
* for mutable/generated ones (ipns, car, tar, and generated HTML).
|
|
4
|
+
*
|
|
5
|
+
* Block and car responses should have different etags to deserialized ones, so
|
|
6
|
+
* you can add a prefix like we do in the existing gateway.
|
|
21
7
|
*
|
|
22
8
|
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
|
|
23
9
|
* @see https://specs.ipfs.tech/http-gateways/path-gateway/#etag-response-header
|
|
24
10
|
*/
|
|
25
|
-
export function getETag({ cid,
|
|
26
|
-
const prefix =
|
|
27
|
-
let suffix =
|
|
11
|
+
export function getETag({ cid, contentType, rangeStart, rangeEnd, contentPrefix }) {
|
|
12
|
+
const prefix = contentType.immutable ? '' : 'W/';
|
|
13
|
+
let suffix = contentType.etag;
|
|
28
14
|
if (rangeStart != null || rangeEnd != null) {
|
|
29
15
|
suffix += `.${rangeStart ?? '0'}-${rangeEnd ?? 'N'}`;
|
|
30
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-e-tag.js","sourceRoot":"","sources":["../../../src/utils/get-e-tag.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-e-tag.js","sourceRoot":"","sources":["../../../src/utils/get-e-tag.ts"],"names":[],"mappings":"AA8BA;;;;;;;;;GASG;AACH,MAAM,UAAU,OAAO,CAAE,EAAE,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAc;IAC5F,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAChD,IAAI,MAAM,GAAG,WAAW,CAAC,IAAI,CAAA;IAE7B,IAAI,UAAU,IAAI,IAAI,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;QAC3C,MAAM,IAAI,IAAI,UAAU,IAAI,GAAG,IAAI,QAAQ,IAAI,GAAG,EAAE,CAAA;IACtD,CAAC;IAED,OAAO,GAAG,MAAM,IAAI,aAAa,IAAI,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAA;AACtE,CAAC"}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* N.b. Range start (zero indexed, inclusive) and end (inclusive) - this is
|
|
3
|
+
* different to `Uint8Array.subarray` which is end exclusive.
|
|
4
|
+
*/
|
|
5
|
+
export declare function rangeToOffsetAndLength(size: bigint | number, start?: number | bigint, end?: number | bigint): {
|
|
6
|
+
offset: number;
|
|
7
|
+
length: number;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Translate `from:to` zero-indexed inclusive bytes to offset/length
|
|
11
|
+
*/
|
|
12
|
+
export declare function entityBytesToOffsetAndLength(size: number | bigint, entityBytes?: string | null): {
|
|
3
13
|
offset: number;
|
|
4
14
|
length: number;
|
|
5
15
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-offset-and-length.d.ts","sourceRoot":"","sources":["../../../src/utils/get-offset-and-length.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-offset-and-length.d.ts","sourceRoot":"","sources":["../../../src/utils/get-offset-and-length.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,wBAAgB,sBAAsB,CAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAsCjJ;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAOpI"}
|
|
@@ -1,19 +1,61 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { InvalidRangeError } from "../errors.js";
|
|
2
|
+
function downCast({ offset, length }) {
|
|
3
|
+
return {
|
|
4
|
+
offset: Number(offset),
|
|
5
|
+
length: Number(length)
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* N.b. Range start (zero indexed, inclusive) and end (inclusive) - this is
|
|
10
|
+
* different to `Uint8Array.subarray` which is end exclusive.
|
|
11
|
+
*/
|
|
12
|
+
export function rangeToOffsetAndLength(size, start, end) {
|
|
13
|
+
size = BigInt(size);
|
|
14
|
+
if (start != null) {
|
|
15
|
+
start = BigInt(start);
|
|
16
|
+
if (start < 0n) {
|
|
17
|
+
throw new InvalidRangeError('Range start cannot be negative');
|
|
18
|
+
}
|
|
19
|
+
if (start >= size) {
|
|
20
|
+
throw new InvalidRangeError('Range start cannot be larger than total bytes');
|
|
21
|
+
}
|
|
7
22
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
23
|
+
if (end != null) {
|
|
24
|
+
end = BigInt(end);
|
|
25
|
+
const abs = end > 0n ? end : -end;
|
|
26
|
+
if (abs >= size) {
|
|
27
|
+
throw new InvalidRangeError('Range end cannot be larger than total bytes');
|
|
28
|
+
}
|
|
29
|
+
if (end < 0n) {
|
|
30
|
+
if (start == null) {
|
|
31
|
+
start = size + end;
|
|
32
|
+
end = size - 1n;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw new InvalidRangeError('Range end cannot be negative');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// make inclusive end exclusive
|
|
39
|
+
end += 1n;
|
|
13
40
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
41
|
+
return downCast(toOffsetAndLength(size, start, end));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Translate `from:to` zero-indexed inclusive bytes to offset/length
|
|
45
|
+
*/
|
|
46
|
+
export function entityBytesToOffsetAndLength(size, entityBytes) {
|
|
47
|
+
size = BigInt(size);
|
|
48
|
+
const parts = (entityBytes ?? '0:*').split(':');
|
|
49
|
+
const start = BigInt(parts[0]);
|
|
50
|
+
const end = parts[1] === '*' ? size : BigInt(parts[1]);
|
|
51
|
+
return downCast(toOffsetAndLength(size, start, end));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Translate `from:to` zero-indexed inclusive bytes to offset/length
|
|
55
|
+
*/
|
|
56
|
+
function toOffsetAndLength(size, start = 0n, end = size) {
|
|
57
|
+
if (start >= 0n) {
|
|
58
|
+
if (end >= 0n) {
|
|
17
59
|
return {
|
|
18
60
|
offset: start,
|
|
19
61
|
length: end - start
|
|
@@ -22,25 +64,25 @@ export function getOffsetAndLength(entry, entityBytes) {
|
|
|
22
64
|
else {
|
|
23
65
|
return {
|
|
24
66
|
offset: start,
|
|
25
|
-
length: (
|
|
67
|
+
length: (size - start) + end
|
|
26
68
|
};
|
|
27
69
|
}
|
|
28
70
|
}
|
|
29
71
|
// start < 0
|
|
30
|
-
let offset =
|
|
31
|
-
if (Math.abs(start) >
|
|
32
|
-
offset =
|
|
72
|
+
let offset = size + start;
|
|
73
|
+
if (Math.abs(Number(start)) > Number(size)) {
|
|
74
|
+
offset = 0n;
|
|
33
75
|
}
|
|
34
|
-
if (end >=
|
|
76
|
+
if (end >= 0n) {
|
|
35
77
|
return {
|
|
36
78
|
offset,
|
|
37
|
-
length:
|
|
79
|
+
length: end - offset
|
|
38
80
|
};
|
|
39
81
|
}
|
|
40
82
|
// end < 0
|
|
41
83
|
return {
|
|
42
84
|
offset,
|
|
43
|
-
length: (
|
|
85
|
+
length: (size - offset) + end
|
|
44
86
|
};
|
|
45
87
|
}
|
|
46
88
|
//# sourceMappingURL=get-offset-and-length.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-offset-and-length.js","sourceRoot":"","sources":["../../../src/utils/get-offset-and-length.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-offset-and-length.js","sourceRoot":"","sources":["../../../src/utils/get-offset-and-length.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Range
|
|
3
|
+
*/
|
|
4
|
+
export interface Range {
|
|
5
|
+
/**
|
|
6
|
+
* Where the range starts, zero indexed
|
|
7
|
+
*/
|
|
8
|
+
start?: number;
|
|
9
|
+
/**
|
|
10
|
+
* Where the range ends, inclusive
|
|
11
|
+
*/
|
|
12
|
+
end?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Range
|
|
16
|
+
*/
|
|
17
|
+
export interface RangeHeader {
|
|
18
|
+
multipartBoundary: string;
|
|
19
|
+
ranges: Range[];
|
|
20
|
+
}
|
|
21
|
+
export declare function getRangeHeader(resource: string, headers: Headers): RangeHeader | undefined | Response;
|
|
22
|
+
//# sourceMappingURL=get-range-header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-range-header.d.ts","sourceRoot":"","sources":["../../../src/utils/get-range-header.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iBAAiB,EAAE,MAAM,CAAA;IACzB,MAAM,EAAE,KAAK,EAAE,CAAA;CAChB;AAwDD,wBAAgB,cAAc,CAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CA0BtG"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { InvalidRangeError } from "../errors.js";
|
|
2
|
+
import { badRequestResponse, notSatisfiableResponse } from "./responses.js";
|
|
3
|
+
function parseValue(val) {
|
|
4
|
+
if (val == null || val === '') {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
const num = Number(val);
|
|
8
|
+
if (isNaN(num)) {
|
|
9
|
+
throw new InvalidRangeError(`Invalid range specification: could not parse "${num}" as number`);
|
|
10
|
+
}
|
|
11
|
+
return num;
|
|
12
|
+
}
|
|
13
|
+
function getByteRangeFromHeader(rangeHeader) {
|
|
14
|
+
if (rangeHeader == null || rangeHeader === '') {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Range: bytes=<start>-<end> | bytes=<start2>- | bytes=-<end2> | bytes=<start1>-<end1>,<start2>-<end2>,...
|
|
19
|
+
*/
|
|
20
|
+
if (!rangeHeader.startsWith('bytes=')) {
|
|
21
|
+
throw new InvalidRangeError('Invalid range request');
|
|
22
|
+
}
|
|
23
|
+
const rangesStr = rangeHeader.substring(6); // Remove "bytes=" prefix
|
|
24
|
+
const rangeParts = rangesStr.split(',').map(part => part.trim());
|
|
25
|
+
const ranges = [];
|
|
26
|
+
for (const part of rangeParts) {
|
|
27
|
+
const match = part.match(/^(?<start>\d+)?-(?<end>\d+)?$/);
|
|
28
|
+
if (match?.groups == null) {
|
|
29
|
+
throw new InvalidRangeError(`Invalid range specification: ${part}`);
|
|
30
|
+
}
|
|
31
|
+
if (part.startsWith('-')) {
|
|
32
|
+
ranges.push({
|
|
33
|
+
end: parseValue(part)
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const { start, end } = match.groups;
|
|
38
|
+
ranges.push({
|
|
39
|
+
start: parseValue(start),
|
|
40
|
+
end: parseValue(end)
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return ranges;
|
|
45
|
+
}
|
|
46
|
+
export function getRangeHeader(resource, headers) {
|
|
47
|
+
const header = headers.get('range');
|
|
48
|
+
// not a range request
|
|
49
|
+
if (header == null) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const ranges = getByteRangeFromHeader(header);
|
|
54
|
+
if (ranges.length === 0) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
multipartBoundary: `multipart_byteranges_${Math.floor(Math.random() * 1_000_000_000)}`,
|
|
59
|
+
ranges
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
if (e.name === 'InvalidRangeError') {
|
|
64
|
+
return notSatisfiableResponse(resource);
|
|
65
|
+
}
|
|
66
|
+
return badRequestResponse(resource, e);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=get-range-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-range-header.js","sourceRoot":"","sources":["../../../src/utils/get-range-header.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const SUBDOMAIN_GATEWAY_REGEX: RegExp;
|
|
1
2
|
export interface ParsedURL {
|
|
2
3
|
url: URL;
|
|
3
4
|
protocol: 'ipfs' | 'ipns';
|
|
@@ -18,5 +19,5 @@ export interface ParsedURL {
|
|
|
18
19
|
* - http://example.com/ipfs/cid/path
|
|
19
20
|
* - http://example.com/ipns/name/path
|
|
20
21
|
*/
|
|
21
|
-
export declare function parseURLString(urlString: string):
|
|
22
|
+
export declare function parseURLString(urlString: string): URL;
|
|
22
23
|
//# sourceMappingURL=parse-url-string.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-url-string.d.ts","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parse-url-string.d.ts","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,uBAAuB,QAAsE,CAAA;AAmB1G,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,GAAG,CAAC;IACT,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC1B,QAAQ,EAAE,MAAM,CAAA;CACjB;AA4FD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAE,SAAS,EAAE,MAAM,GAAG,GAAG,CAuBtD"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { InvalidParametersError } from '@libp2p/interface';
|
|
2
|
+
import { peerIdFromCID, peerIdFromString } from '@libp2p/peer-id';
|
|
3
|
+
import { CID } from 'multiformats/cid';
|
|
2
4
|
import { decodeDNSLinkLabel, isInlinedDnsLink } from "./dnslink-label.js";
|
|
3
5
|
import { ipfsPathToUrl, ipfsUrlToUrl } from "./ipfs-path-to-url.js";
|
|
4
|
-
const SUBDOMAIN_GATEWAY_REGEX = /^(?<cidOrPeerIdOrDnsLink>[^/?]+)\.(?<protocol>ip[fn]s)\.([^/?]+)$/;
|
|
6
|
+
export const SUBDOMAIN_GATEWAY_REGEX = /^(?<cidOrPeerIdOrDnsLink>[^/?]+)\.(?<protocol>ip[fn]s)\.([^/?]+)$/;
|
|
7
|
+
const CODEC_LIBP2P_KEY = 0x72;
|
|
5
8
|
function matchSubdomainGroupsGuard(groups) {
|
|
6
9
|
const protocol = groups?.protocol;
|
|
7
10
|
if (protocol !== 'ipfs' && protocol !== 'ipns') {
|
|
@@ -13,31 +16,6 @@ function matchSubdomainGroupsGuard(groups) {
|
|
|
13
16
|
}
|
|
14
17
|
return true;
|
|
15
18
|
}
|
|
16
|
-
function toQuery(query) {
|
|
17
|
-
if (query == null) {
|
|
18
|
-
return {};
|
|
19
|
-
}
|
|
20
|
-
const output = {};
|
|
21
|
-
for (const [key, value] of query.entries()) {
|
|
22
|
-
output[key] = value;
|
|
23
|
-
if (value === 'true') {
|
|
24
|
-
output[key] = true;
|
|
25
|
-
}
|
|
26
|
-
if (value === 'false') {
|
|
27
|
-
output[key] = false;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return output;
|
|
31
|
-
}
|
|
32
|
-
function stripLeadingHash(pathname) {
|
|
33
|
-
return stripLeading(pathname, '#');
|
|
34
|
-
}
|
|
35
|
-
function stripLeading(str, char) {
|
|
36
|
-
while (str.startsWith(char)) {
|
|
37
|
-
str = str.substring(1);
|
|
38
|
-
}
|
|
39
|
-
return str;
|
|
40
|
-
}
|
|
41
19
|
/**
|
|
42
20
|
* If the caller has passed a case-sensitive identifier (like a base58btc
|
|
43
21
|
* encoded CID or PeerId) in a case-insensitive location (like a subdomain),
|
|
@@ -50,7 +28,10 @@ function findOriginalCidOrPeer(needle, haystack) {
|
|
|
50
28
|
}
|
|
51
29
|
return haystack.substring(start, start + needle.length);
|
|
52
30
|
}
|
|
53
|
-
function
|
|
31
|
+
function stringToUrl(urlString) {
|
|
32
|
+
if (urlString instanceof URL) {
|
|
33
|
+
return urlString;
|
|
34
|
+
}
|
|
54
35
|
// turn IPFS/IPNS path into gateway URL string
|
|
55
36
|
if (urlString.startsWith('/ipfs/') || urlString.startsWith('/ipns/')) {
|
|
56
37
|
urlString = ipfsPathToUrl(urlString);
|
|
@@ -64,21 +45,9 @@ function toUrl(urlString) {
|
|
|
64
45
|
}
|
|
65
46
|
throw new InvalidParametersError(`Invalid URL: ${urlString}`);
|
|
66
47
|
}
|
|
67
|
-
|
|
68
|
-
* Accepts the following url strings:
|
|
69
|
-
*
|
|
70
|
-
* - /ipfs/Qmfoo/path
|
|
71
|
-
* - /ipns/Qmfoo/path
|
|
72
|
-
* - ipfs://cid/path
|
|
73
|
-
* - ipns://name/path
|
|
74
|
-
* - http://cid.ipfs.example.com/path
|
|
75
|
-
* - http://name.ipns.example.com/path
|
|
76
|
-
* - http://example.com/ipfs/cid/path
|
|
77
|
-
* - http://example.com/ipns/name/path
|
|
78
|
-
*/
|
|
79
|
-
export function parseURLString(urlString) {
|
|
48
|
+
function toURL(urlString) {
|
|
80
49
|
// validate url
|
|
81
|
-
const url =
|
|
50
|
+
const url = stringToUrl(urlString);
|
|
82
51
|
// test for subdomain gateway URL
|
|
83
52
|
const subdomainMatch = url.hostname.match(SUBDOMAIN_GATEWAY_REGEX);
|
|
84
53
|
if (matchSubdomainGroupsGuard(subdomainMatch?.groups)) {
|
|
@@ -93,16 +62,7 @@ export function parseURLString(urlString) {
|
|
|
93
62
|
// present in the string URL and we need to be able to round-trip the user's
|
|
94
63
|
// input while also maintaining a sane canonical URL for the resource. Phew.
|
|
95
64
|
const wat = new URL(`not-${urlString}`);
|
|
96
|
-
return {
|
|
97
|
-
url: new URL(`${groups.protocol}://${cidOrPeerIdOrDnsLink}${wat.pathname}${url.search}${url.hash}`),
|
|
98
|
-
protocol: groups.protocol,
|
|
99
|
-
cidOrPeerIdOrDnsLink,
|
|
100
|
-
path: url.pathname.split('/')
|
|
101
|
-
.filter(str => str !== '')
|
|
102
|
-
.map(str => decodeURIComponent(str)),
|
|
103
|
-
query: toQuery(url.searchParams),
|
|
104
|
-
fragment: stripLeadingHash(url.hash)
|
|
105
|
-
};
|
|
65
|
+
return new URL(`${groups.protocol}://${cidOrPeerIdOrDnsLink}${wat.pathname}${url.search}${url.hash}`);
|
|
106
66
|
}
|
|
107
67
|
// test for IPFS path gateway URL
|
|
108
68
|
if (url.pathname.startsWith('/ipfs/')) {
|
|
@@ -111,16 +71,7 @@ export function parseURLString(urlString) {
|
|
|
111
71
|
if (cid == null) {
|
|
112
72
|
throw new InvalidParametersError(`Path gateway URL ${urlString} had no CID`);
|
|
113
73
|
}
|
|
114
|
-
return {
|
|
115
|
-
url: new URL(`ipfs://${cid}${url.pathname.replace(`/ipfs/${cid}`, '')}${url.search}${url.hash}`),
|
|
116
|
-
protocol: 'ipfs',
|
|
117
|
-
cidOrPeerIdOrDnsLink: cid,
|
|
118
|
-
path: parts
|
|
119
|
-
.filter(str => str !== '')
|
|
120
|
-
.map(str => decodeURIComponent(str)),
|
|
121
|
-
query: toQuery(url.searchParams),
|
|
122
|
-
fragment: stripLeadingHash(url.hash)
|
|
123
|
-
};
|
|
74
|
+
return new URL(`ipfs://${cid}${url.pathname.replace(`/ipfs/${cid}`, '')}${url.search}${url.hash}`);
|
|
124
75
|
}
|
|
125
76
|
// test for IPNS path gateway URL
|
|
126
77
|
if (url.pathname.startsWith('/ipns/')) {
|
|
@@ -129,17 +80,41 @@ export function parseURLString(urlString) {
|
|
|
129
80
|
if (name == null) {
|
|
130
81
|
throw new InvalidParametersError(`Path gateway URL ${urlString} had no name`);
|
|
131
82
|
}
|
|
132
|
-
return {
|
|
133
|
-
url: new URL(`ipns://${name}${url.pathname.replace(`/ipns/${name}`, '')}${url.search}${url.hash}`),
|
|
134
|
-
protocol: 'ipns',
|
|
135
|
-
cidOrPeerIdOrDnsLink: name,
|
|
136
|
-
path: parts
|
|
137
|
-
.filter(str => str !== '')
|
|
138
|
-
.map(str => decodeURIComponent(str)),
|
|
139
|
-
query: toQuery(url.searchParams),
|
|
140
|
-
fragment: stripLeadingHash(url.hash)
|
|
141
|
-
};
|
|
83
|
+
return new URL(`ipns://${name}${url.pathname.replace(`/ipns/${name}`, '')}${url.search}${url.hash}`);
|
|
142
84
|
}
|
|
143
85
|
throw new TypeError(`Invalid URL: ${urlString}, please use ipfs://, ipns://, or gateway URLs only`);
|
|
144
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Accepts the following url strings:
|
|
89
|
+
*
|
|
90
|
+
* - /ipfs/Qmfoo/path
|
|
91
|
+
* - /ipns/Qmfoo/path
|
|
92
|
+
* - ipfs://cid/path
|
|
93
|
+
* - ipns://name/path
|
|
94
|
+
* - http://cid.ipfs.example.com/path
|
|
95
|
+
* - http://name.ipns.example.com/path
|
|
96
|
+
* - http://example.com/ipfs/cid/path
|
|
97
|
+
* - http://example.com/ipns/name/path
|
|
98
|
+
*/
|
|
99
|
+
export function parseURLString(urlString) {
|
|
100
|
+
// validate url
|
|
101
|
+
const url = toURL(urlString);
|
|
102
|
+
// treat IPNS keys that do not parse as PeerIds as DNSLink
|
|
103
|
+
if (url.protocol === 'ipns:') {
|
|
104
|
+
try {
|
|
105
|
+
peerIdFromString(url.hostname);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
url.protocol = 'dnslink:';
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (url.protocol === 'ipfs:') {
|
|
112
|
+
const cid = CID.parse(url.hostname);
|
|
113
|
+
// special case - peer id encoded as a CID
|
|
114
|
+
if (cid.code === CODEC_LIBP2P_KEY) {
|
|
115
|
+
return new URL(`ipns://${peerIdFromCID(cid)}${url.pathname}${url.search}${url.hash}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return url;
|
|
119
|
+
}
|
|
145
120
|
//# sourceMappingURL=parse-url-string.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-url-string.js","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACzE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAOnE,MAAM,uBAAuB,GAAG,mEAAmE,CAAA;
|
|
1
|
+
{"version":3,"file":"parse-url-string.js","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,9 +6,9 @@ import { CID } from 'multiformats/cid';
|
|
|
6
6
|
* E.g.
|
|
7
7
|
*
|
|
8
8
|
* - Qmfoo -> /ipfs/Qmfoo
|
|
9
|
-
* - https://Qmfoo.ipfs.gateway.org ->
|
|
10
|
-
* - https://gateway.org/ipfs/Qmfoo ->
|
|
11
|
-
* - https://gateway.org/ipfs/Qmfoo/bar.txt ->
|
|
9
|
+
* - https://Qmfoo.ipfs.gateway.org -> ipfs://Qmfoo
|
|
10
|
+
* - https://gateway.org/ipfs/Qmfoo -> ipfs://Qmfoo
|
|
11
|
+
* - https://gateway.org/ipfs/Qmfoo/bar.txt -> ipfs://Qmfoo
|
|
12
12
|
* - etc
|
|
13
13
|
*/
|
|
14
14
|
export declare function resourceToSessionCacheKey(url: string | CID): string;
|
|
@@ -7,9 +7,9 @@ import { parseURLString } from './parse-url-string.js';
|
|
|
7
7
|
* E.g.
|
|
8
8
|
*
|
|
9
9
|
* - Qmfoo -> /ipfs/Qmfoo
|
|
10
|
-
* - https://Qmfoo.ipfs.gateway.org ->
|
|
11
|
-
* - https://gateway.org/ipfs/Qmfoo ->
|
|
12
|
-
* - https://gateway.org/ipfs/Qmfoo/bar.txt ->
|
|
10
|
+
* - https://Qmfoo.ipfs.gateway.org -> ipfs://Qmfoo
|
|
11
|
+
* - https://gateway.org/ipfs/Qmfoo -> ipfs://Qmfoo
|
|
12
|
+
* - https://gateway.org/ipfs/Qmfoo/bar.txt -> ipfs://Qmfoo
|
|
13
13
|
* - etc
|
|
14
14
|
*/
|
|
15
15
|
export function resourceToSessionCacheKey(url) {
|
|
@@ -21,7 +21,7 @@ export function resourceToSessionCacheKey(url) {
|
|
|
21
21
|
return `ipfs://${CID.parse(url.toString())}`;
|
|
22
22
|
}
|
|
23
23
|
catch { }
|
|
24
|
-
const { protocol,
|
|
25
|
-
return `${protocol}
|
|
24
|
+
const { protocol, host } = parseURLString(url.toString());
|
|
25
|
+
return `${protocol}//${host}`;
|
|
26
26
|
}
|
|
27
27
|
//# sourceMappingURL=resource-to-cache-key.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-to-cache-key.js","sourceRoot":"","sources":["../../../src/utils/resource-to-cache-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEtD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,yBAAyB,CAAE,GAAiB;IAC1D,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAE1B,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QAChB,OAAO,UAAU,GAAG,EAAE,CAAA;IACxB,CAAC;IAED,IAAI,CAAC;QACH,OAAO,UAAU,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAA;IAC9C,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,MAAM,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"resource-to-cache-key.js","sourceRoot":"","sources":["../../../src/utils/resource-to-cache-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEtD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,yBAAyB,CAAE,GAAiB;IAC1D,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAE1B,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QAChB,OAAO,UAAU,GAAG,EAAE,CAAA;IACxB,CAAC;IAED,IAAI,CAAC;QACH,OAAO,UAAU,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAA;IAC9C,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;IAEzD,OAAO,GAAG,QAAQ,KAAK,IAAI,EAAE,CAAA;AAC/B,CAAC"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { CID } from 'multiformats/cid';
|
|
2
1
|
interface CacheControlHeaderOptions {
|
|
3
2
|
/**
|
|
4
3
|
* This should be seconds as a number.
|
|
@@ -18,22 +17,13 @@ interface CacheControlHeaderOptions {
|
|
|
18
17
|
*/
|
|
19
18
|
export declare function setCacheControlHeader({ ttl, protocol, response }: CacheControlHeaderOptions): void;
|
|
20
19
|
/**
|
|
21
|
-
* This function returns the value of the `Content-Range` header for a given
|
|
20
|
+
* This function returns the value of the `Content-Range` header for a given
|
|
21
|
+
* range.
|
|
22
|
+
*
|
|
22
23
|
* If you know the total size of the body, pass it as `byteSize`
|
|
23
24
|
*
|
|
24
25
|
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range
|
|
25
26
|
*/
|
|
26
|
-
export declare function getContentRangeHeader(
|
|
27
|
-
byteStart: number | undefined;
|
|
28
|
-
byteEnd: number | undefined;
|
|
29
|
-
byteSize: number | undefined;
|
|
30
|
-
}): string;
|
|
31
|
-
/**
|
|
32
|
-
* Sets the `X-Ipfs-Roots` header on the response if it exists.
|
|
33
|
-
*
|
|
34
|
-
* @see https://specs.ipfs.tech/http-gateways/path-gateway/#x-ipfs-roots-response-header
|
|
35
|
-
*/
|
|
36
|
-
export declare function setIpfsRoots(response: Response, ipfsRoots?: CID[]): void;
|
|
37
|
-
export declare function getIpfsRoots(ipfsRoots: CID[]): string;
|
|
27
|
+
export declare function getContentRangeHeader(byteSize: number | bigint | string, byteStart?: number | bigint | string, byteEnd?: number | bigint | string): string;
|
|
38
28
|
export {};
|
|
39
29
|
//# sourceMappingURL=response-headers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-headers.d.ts","sourceRoot":"","sources":["../../../src/utils/response-headers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"response-headers.d.ts","sourceRoot":"","sources":["../../../src/utils/response-headers.ts"],"names":[],"mappings":"AAEA,UAAU,yBAAyB;IACjC;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,yBAAyB,GAAG,IAAI,CAsBnG;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CA8C3J"}
|