@helia/verified-fetch 3.2.2 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/index.min.js +81 -71
- package/dist/index.min.js.map +4 -4
- package/dist/src/constants.d.ts +2 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +2 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/index.d.ts +57 -13
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -6
- package/dist/src/index.js.map +1 -1
- package/dist/src/plugins/plugin-handle-car.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-car.js +37 -27
- package/dist/src/plugins/plugin-handle-car.js.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.d.ts +1 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.js +1 -1
- package/dist/src/plugins/plugin-handle-dag-cbor-html-preview.js.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-cbor.js +5 -5
- package/dist/src/plugins/plugin-handle-dag-cbor.js.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-pb.js +12 -12
- package/dist/src/plugins/plugin-handle-dag-pb.js.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-walk.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-dag-walk.js +5 -4
- package/dist/src/plugins/plugin-handle-dag-walk.js.map +1 -1
- package/dist/src/plugins/plugin-handle-ipns-record.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-ipns-record.js +13 -19
- package/dist/src/plugins/plugin-handle-ipns-record.js.map +1 -1
- package/dist/src/plugins/plugin-handle-json.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-json.js +5 -4
- package/dist/src/plugins/plugin-handle-json.js.map +1 -1
- package/dist/src/plugins/plugin-handle-raw.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-raw.js +18 -5
- package/dist/src/plugins/plugin-handle-raw.js.map +1 -1
- package/dist/src/plugins/plugin-handle-tar.js +1 -1
- package/dist/src/plugins/plugin-handle-tar.js.map +1 -1
- package/dist/src/plugins/types.d.ts +10 -8
- package/dist/src/plugins/types.d.ts.map +1 -1
- package/dist/src/url-resolver.d.ts +21 -0
- package/dist/src/url-resolver.d.ts.map +1 -0
- package/dist/src/url-resolver.js +118 -0
- package/dist/src/url-resolver.js.map +1 -0
- package/dist/src/utils/byte-range-context.d.ts +1 -1
- package/dist/src/utils/content-type-parser.d.ts.map +1 -1
- package/dist/src/utils/content-type-parser.js +3 -0
- package/dist/src/utils/content-type-parser.js.map +1 -1
- package/dist/src/utils/get-content-type.d.ts +3 -3
- package/dist/src/utils/get-content-type.d.ts.map +1 -1
- package/dist/src/utils/get-content-type.js +1 -1
- package/dist/src/utils/get-content-type.js.map +1 -1
- package/dist/src/utils/get-e-tag.d.ts +1 -1
- package/dist/src/utils/get-offset-and-length.d.ts +6 -0
- package/dist/src/utils/get-offset-and-length.d.ts.map +1 -0
- package/dist/src/utils/get-offset-and-length.js +46 -0
- package/dist/src/utils/get-offset-and-length.js.map +1 -0
- package/dist/src/utils/get-resolved-accept-header.d.ts +2 -2
- package/dist/src/utils/get-resolved-accept-header.d.ts.map +1 -1
- package/dist/src/utils/handle-redirects.d.ts.map +1 -1
- package/dist/src/utils/handle-redirects.js +3 -3
- package/dist/src/utils/handle-redirects.js.map +1 -1
- package/dist/src/utils/ipfs-path-to-string.d.ts +6 -0
- package/dist/src/utils/ipfs-path-to-string.d.ts.map +1 -0
- package/dist/src/utils/ipfs-path-to-string.js +10 -0
- package/dist/src/utils/ipfs-path-to-string.js.map +1 -0
- package/dist/src/utils/is-accept-explicit.d.ts +6 -4
- package/dist/src/utils/is-accept-explicit.d.ts.map +1 -1
- package/dist/src/utils/is-accept-explicit.js +7 -4
- package/dist/src/utils/is-accept-explicit.js.map +1 -1
- package/dist/src/utils/parse-url-string.d.ts +1 -55
- package/dist/src/utils/parse-url-string.d.ts.map +1 -1
- package/dist/src/utils/parse-url-string.js +16 -217
- package/dist/src/utils/parse-url-string.js.map +1 -1
- package/dist/src/utils/response-headers.d.ts +1 -1
- package/dist/src/utils/response-headers.d.ts.map +1 -1
- package/dist/src/utils/responses.d.ts +1 -1
- package/dist/src/utils/select-output-type.d.ts +6 -2
- package/dist/src/utils/select-output-type.d.ts.map +1 -1
- package/dist/src/utils/select-output-type.js +28 -37
- package/dist/src/utils/select-output-type.js.map +1 -1
- package/dist/src/utils/server-timing.d.ts +5 -11
- package/dist/src/utils/server-timing.d.ts.map +1 -1
- package/dist/src/utils/server-timing.js +17 -15
- package/dist/src/utils/server-timing.js.map +1 -1
- package/dist/src/utils/walk-path.js +1 -1
- package/dist/src/utils/walk-path.js.map +1 -1
- package/dist/src/verified-fetch.d.ts +3 -10
- package/dist/src/verified-fetch.d.ts.map +1 -1
- package/dist/src/verified-fetch.js +68 -57
- package/dist/src/verified-fetch.js.map +1 -1
- package/dist/typedoc-urls.json +13 -2
- package/package.json +35 -36
- package/src/constants.ts +1 -0
- package/src/index.ts +73 -22
- package/src/plugins/plugin-handle-car.ts +54 -30
- package/src/plugins/plugin-handle-dag-cbor-html-preview.ts +2 -2
- package/src/plugins/plugin-handle-dag-cbor.ts +5 -5
- package/src/plugins/plugin-handle-dag-pb.ts +12 -12
- package/src/plugins/plugin-handle-dag-walk.ts +5 -4
- package/src/plugins/plugin-handle-ipns-record.ts +16 -19
- package/src/plugins/plugin-handle-json.ts +5 -4
- package/src/plugins/plugin-handle-raw.ts +21 -6
- package/src/plugins/plugin-handle-tar.ts +1 -1
- package/src/plugins/types.ts +12 -8
- package/src/url-resolver.ts +159 -0
- package/src/utils/byte-range-context.ts +1 -1
- package/src/utils/content-type-parser.ts +3 -0
- package/src/utils/get-content-type.ts +5 -4
- package/src/utils/get-e-tag.ts +1 -1
- package/src/utils/get-offset-and-length.ts +54 -0
- package/src/utils/get-resolved-accept-header.ts +2 -2
- package/src/utils/handle-redirects.ts +10 -3
- package/src/utils/ipfs-path-to-string.ts +9 -0
- package/src/utils/is-accept-explicit.ts +14 -7
- package/src/utils/parse-url-string.ts +20 -286
- package/src/utils/response-headers.ts +1 -1
- package/src/utils/responses.ts +1 -1
- package/src/utils/select-output-type.ts +38 -44
- package/src/utils/server-timing.ts +17 -30
- package/src/utils/walk-path.ts +1 -1
- package/src/verified-fetch.ts +78 -69
- package/dist/src/types.d.ts +0 -16
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js +0 -2
- package/dist/src/types.js.map +0 -1
- package/dist/src/utils/parse-resource.d.ts +0 -18
- package/dist/src/utils/parse-resource.d.ts.map +0 -1
- package/dist/src/utils/parse-resource.js +0 -27
- package/dist/src/utils/parse-resource.js.map +0 -1
- package/src/types.ts +0 -17
- package/src/utils/parse-resource.ts +0 -42
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-url-string.js","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"parse-url-string.js","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"AAAA,MAAM,SAAS,GAAG,4FAA4F,CAAA;AAC9G,MAAM,UAAU,GAAG,2FAA2F,CAAA;AAC9G,MAAM,kBAAkB,GAAG,8GAA8G,CAAA;AACzI,MAAM,uBAAuB,GAAG,8GAA8G,CAAA;AAS9I,SAAS,mBAAmB,CAAE,MAA6D;IACzF,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,CAAA;IACjC,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;QAAC,OAAO,KAAK,CAAA;IAAC,CAAC;IACtC,MAAM,oBAAoB,GAAG,MAAM,EAAE,oBAAoB,CAAA;IACzD,IAAI,oBAAoB,IAAI,IAAI,EAAE,CAAC;QAAC,OAAO,KAAK,CAAA;IAAC,CAAC;IAClD,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,CAAA;IACzB,MAAM,KAAK,GAAG,MAAM,EAAE,KAAK,CAAA;IAE3B,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACxC,OAAO,oBAAoB,KAAK,QAAQ;QACxC,CAAC,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC;QAC1C,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAA;AAChD,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,cAAc,CAAE,SAAiB;IAC/C,KAAK,MAAM,OAAO,IAAI,CAAC,uBAAuB,EAAE,SAAS,EAAE,kBAAkB,EAAE,UAAU,CAAC,EAAE,CAAC;QAC3F,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAEtC,IAAI,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,MAA+B,CAAA;YAEpD,IAAI,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;gBACxB,MAAM,CAAC,IAAI,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YAC/C,CAAC;YAED,0CAA0C;YAC1C,IAAI,OAAO,KAAK,uBAAuB,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,IAAI,gBAAgB,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE,CAAC;gBACvH,MAAM,CAAC,oBAAoB,GAAG,mBAAmB,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAA;YAChF,CAAC;YAED,OAAO,MAAM,CAAA;QACf,CAAC;IACH,CAAC;IAED,MAAM,IAAI,SAAS,CAAC,gBAAgB,SAAS,qDAAqD,CAAC,CAAA;AACrG,CAAC;AAED;;;GAGG;AAEH,qEAAqE;AACrE,uEAAuE;AACvE,MAAM,aAAa,GAAG,+CAA+C,CAAA;AAErE;;;GAGG;AACH,SAAS,gBAAgB,CAAE,KAAa;IACtC,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;AACjF,CAAC;AAED;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAE,SAAiB;IAC7C,OAAO,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAC5E,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-headers.d.ts","sourceRoot":"","sources":["../../../src/utils/response-headers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAE3C,UAAU,yBAAyB;IACjC;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"response-headers.d.ts","sourceRoot":"","sources":["../../../src/utils/response-headers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAE3C,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,CAoBnG;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAE,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;IAAE,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAAG,MAAM,CAmC7K;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI,CAIzE;AAED,wBAAgB,YAAY,CAAE,SAAS,EAAE,GAAG,EAAE,GAAG,MAAM,CAEtD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ByteRangeContext } from './byte-range-context.js';
|
|
2
|
-
import type { SupportedBodyTypes } from '../
|
|
2
|
+
import type { SupportedBodyTypes } from '../index.js';
|
|
3
3
|
import type { Logger } from '@libp2p/interface';
|
|
4
4
|
export interface ResponseOptions extends ResponseInit {
|
|
5
5
|
redirected?: boolean;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import type { RequestFormatShorthand } from '../
|
|
1
|
+
import type { RequestFormatShorthand } from '../index.js';
|
|
2
2
|
import type { CID } from 'multiformats/cid';
|
|
3
|
+
export interface AcceptHeader {
|
|
4
|
+
mimeType: string;
|
|
5
|
+
options: Record<string, string>;
|
|
6
|
+
}
|
|
3
7
|
/**
|
|
4
8
|
* Selects an output mime-type based on the CID and a passed `Accept` header
|
|
5
9
|
*/
|
|
6
|
-
export declare function selectOutputType(cid: CID, accept?: string):
|
|
10
|
+
export declare function selectOutputType(cid: CID, accept?: string): AcceptHeader | undefined;
|
|
7
11
|
export declare const FORMAT_TO_MIME_TYPE: Record<RequestFormatShorthand, string>;
|
|
8
12
|
/**
|
|
9
13
|
* Converts a `format=...` query param to a mime type as would be found in the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select-output-type.d.ts","sourceRoot":"","sources":["../../../src/utils/select-output-type.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AA0D3C;;GAEG;AACH,wBAAgB,gBAAgB,CAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"select-output-type.d.ts","sourceRoot":"","sources":["../../../src/utils/select-output-type.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AA0D3C,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAMrF;AAiED,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,sBAAsB,EAAE,MAAM,CAStE,CAAA;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAE,MAAM,CAAC,EAAE,sBAAsB,GAAG,MAAM,GAAG,SAAS,CAI9F"}
|
|
@@ -72,62 +72,53 @@ function chooseMimeType(accept, validMimeTypes) {
|
|
|
72
72
|
.split(',')
|
|
73
73
|
.map(s => {
|
|
74
74
|
const parts = s.trim().split(';');
|
|
75
|
+
const options = {
|
|
76
|
+
q: '0'
|
|
77
|
+
};
|
|
78
|
+
for (let i = 1; i < parts.length; i++) {
|
|
79
|
+
const [key, value] = parts[i].split('=').map(s => s.trim());
|
|
80
|
+
options[key] = value;
|
|
81
|
+
}
|
|
75
82
|
return {
|
|
76
83
|
mimeType: `${parts[0]}`.trim(),
|
|
77
|
-
|
|
84
|
+
options
|
|
78
85
|
};
|
|
79
86
|
})
|
|
80
87
|
.sort((a, b) => {
|
|
81
|
-
if (a.
|
|
88
|
+
if (a.options.q === b.options.q) {
|
|
82
89
|
return 0;
|
|
83
90
|
}
|
|
84
|
-
if (a.
|
|
91
|
+
if (a.options.q > b.options.q) {
|
|
85
92
|
return -1;
|
|
86
93
|
}
|
|
87
94
|
return 1;
|
|
88
|
-
})
|
|
89
|
-
.map(s => s.mimeType);
|
|
95
|
+
});
|
|
90
96
|
for (const headerFormat of requestedMimeTypes) {
|
|
91
97
|
for (const mimeType of validMimeTypes) {
|
|
92
|
-
if (headerFormat.includes(mimeType)) {
|
|
93
|
-
return
|
|
98
|
+
if (headerFormat.mimeType.includes(mimeType)) {
|
|
99
|
+
return headerFormat;
|
|
94
100
|
}
|
|
95
|
-
if (headerFormat === '*/*') {
|
|
96
|
-
return
|
|
101
|
+
if (headerFormat.mimeType === '*/*') {
|
|
102
|
+
return {
|
|
103
|
+
mimeType,
|
|
104
|
+
options: headerFormat.options
|
|
105
|
+
};
|
|
97
106
|
}
|
|
98
|
-
if (headerFormat.startsWith('*/') && mimeType.split('/')[1] === headerFormat.split('/')[1]) {
|
|
99
|
-
return
|
|
107
|
+
if (headerFormat.mimeType.startsWith('*/') && mimeType.split('/')[1] === headerFormat.mimeType.split('/')[1]) {
|
|
108
|
+
return {
|
|
109
|
+
mimeType,
|
|
110
|
+
options: headerFormat.options
|
|
111
|
+
};
|
|
100
112
|
}
|
|
101
|
-
if (headerFormat.endsWith('/*') && mimeType.split('/')[0] === headerFormat.split('/')[0]) {
|
|
102
|
-
return
|
|
113
|
+
if (headerFormat.mimeType.endsWith('/*') && mimeType.split('/')[0] === headerFormat.mimeType.split('/')[0]) {
|
|
114
|
+
return {
|
|
115
|
+
mimeType,
|
|
116
|
+
options: headerFormat.options
|
|
117
|
+
};
|
|
103
118
|
}
|
|
104
119
|
}
|
|
105
120
|
}
|
|
106
121
|
}
|
|
107
|
-
/**
|
|
108
|
-
* Parses q-factor weighting from the accept header to allow letting some mime
|
|
109
|
-
* types take precedence over others.
|
|
110
|
-
*
|
|
111
|
-
* If the q-factor for an acceptable mime representation is omitted it defaults
|
|
112
|
-
* to `1`.
|
|
113
|
-
*
|
|
114
|
-
* All specified values should be in the range 0-1.
|
|
115
|
-
*
|
|
116
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept#q
|
|
117
|
-
*/
|
|
118
|
-
function parseQFactor(str) {
|
|
119
|
-
if (str != null) {
|
|
120
|
-
str = str.trim();
|
|
121
|
-
}
|
|
122
|
-
if (str?.startsWith('q=') !== true) {
|
|
123
|
-
return 1;
|
|
124
|
-
}
|
|
125
|
-
const factor = parseFloat(str.replace('q=', ''));
|
|
126
|
-
if (isNaN(factor)) {
|
|
127
|
-
return 0;
|
|
128
|
-
}
|
|
129
|
-
return factor;
|
|
130
|
-
}
|
|
131
122
|
export const FORMAT_TO_MIME_TYPE = {
|
|
132
123
|
raw: 'application/vnd.ipld.raw',
|
|
133
124
|
car: 'application/vnd.ipld.car',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select-output-type.js","sourceRoot":"","sources":["../../../src/utils/select-output-type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,EAAE,IAAI,IAAI,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAIzD;;GAEG;AACH,MAAM,YAAY,GAA6B;IAC7C,CAAC,WAAW,CAAC,EAAE;QACb,kBAAkB;QAClB,+BAA+B;QAC/B,kBAAkB;QAClB,+BAA+B;QAC/B,0BAA0B;QAC1B,0BAA0B;QAC1B,kCAAkC;QAClC,0BAA0B;QAC1B,WAAW;KACZ;IACD,CAAC,WAAW,CAAC,EAAE;QACb,kBAAkB;QAClB,+BAA+B;QAC/B,kBAAkB;QAClB,+BAA+B;QAC/B,0BAA0B;QAC1B,0BAA0B;QAC1B,kCAAkC;QAClC,0BAA0B;KAC3B;IACD,CAAC,QAAQ,CAAC,EAAE;QACV,kBAAkB;QAClB,+BAA+B;QAC/B,kBAAkB;QAClB,+BAA+B;QAC/B,0BAA0B;QAC1B,0BAA0B;QAC1B,kCAAkC;QAClC,0BAA0B;KAC3B;IACD,CAAC,SAAS,CAAC,EAAE;QACX,0BAA0B;QAC1B,kBAAkB;QAClB,+BAA+B;QAC/B,kBAAkB;QAClB,+BAA+B;QAC/B,0BAA0B;QAC1B,kCAAkC;QAClC,0BAA0B;QAC1B,mBAAmB;KACpB;IACD,CAAC,OAAO,CAAC,EAAE;QACT,0BAA0B;QAC1B,0BAA0B;QAC1B,kCAAkC;QAClC,+BAA+B;QAC/B,0BAA0B;QAC1B,mBAAmB;KACpB;CACF,CAAA;
|
|
1
|
+
{"version":3,"file":"select-output-type.js","sourceRoot":"","sources":["../../../src/utils/select-output-type.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
export declare class ServerTiming {
|
|
2
|
+
private headers;
|
|
3
|
+
constructor();
|
|
4
|
+
getHeader(): string;
|
|
5
|
+
time<T>(name: string, description: string, promise: Promise<T>): Promise<T>;
|
|
5
6
|
}
|
|
6
|
-
export interface ServerTimingError {
|
|
7
|
-
result: null;
|
|
8
|
-
error: Error;
|
|
9
|
-
header: string;
|
|
10
|
-
}
|
|
11
|
-
export type ServerTimingResult<T> = ServerTimingSuccess<T> | ServerTimingError;
|
|
12
|
-
export declare function serverTiming<T>(name: string, description: string, fn: () => Promise<T>): Promise<ServerTimingResult<T>>;
|
|
13
7
|
//# sourceMappingURL=server-timing.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-timing.d.ts","sourceRoot":"","sources":["../../../src/utils/server-timing.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"server-timing.d.ts","sourceRoot":"","sources":["../../../src/utils/server-timing.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAU;;IAMzB,SAAS,IAAK,MAAM;IAId,IAAI,CAAE,CAAC,EAAG,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAYpF"}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const endTime = performance.now();
|
|
6
|
-
const duration = (endTime - startTime).toFixed(1); // Duration in milliseconds
|
|
7
|
-
// Create the Server-Timing header string
|
|
8
|
-
const header = `${name};dur=${duration};desc="${description}"`;
|
|
9
|
-
return { result, header, error: null };
|
|
1
|
+
export class ServerTiming {
|
|
2
|
+
headers;
|
|
3
|
+
constructor() {
|
|
4
|
+
this.headers = [];
|
|
10
5
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
6
|
+
getHeader() {
|
|
7
|
+
return this.headers.join(',');
|
|
8
|
+
}
|
|
9
|
+
async time(name, description, promise) {
|
|
10
|
+
const startTime = performance.now();
|
|
11
|
+
try {
|
|
12
|
+
return await promise; // Execute the function
|
|
13
|
+
}
|
|
14
|
+
finally {
|
|
15
|
+
const endTime = performance.now();
|
|
16
|
+
const duration = (endTime - startTime).toFixed(1); // Duration in milliseconds
|
|
17
|
+
this.headers.push(`${name};dur=${duration};desc="${description}"`);
|
|
18
|
+
}
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
21
|
//# sourceMappingURL=server-timing.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-timing.js","sourceRoot":"","sources":["../../../src/utils/server-timing.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server-timing.js","sourceRoot":"","sources":["../../../src/utils/server-timing.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,YAAY;IACf,OAAO,CAAU;IAEzB;QACE,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;IACnB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC/B,CAAC;IAED,KAAK,CAAC,IAAI,CAAM,IAAY,EAAE,WAAmB,EAAE,OAAmB;QACpE,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;QAEnC,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAA,CAAC,uBAAuB;QAC9C,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;YACjC,MAAM,QAAQ,GAAG,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA,CAAC,2BAA2B;YAE7E,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,QAAQ,QAAQ,UAAU,WAAW,GAAG,CAAC,CAAA;QACpE,CAAC;IACH,CAAC;CACF"}
|
|
@@ -38,7 +38,7 @@ export async function handlePathWalking({ cid, path, resource, options, blocksto
|
|
|
38
38
|
if (['ERR_NO_PROP', 'ERR_NO_TERMINAL_ELEMENT', 'ERR_NOT_FOUND'].includes(err.code)) {
|
|
39
39
|
return notFoundResponse(resource);
|
|
40
40
|
}
|
|
41
|
-
log.error('error walking path %s', path, err);
|
|
41
|
+
log.error('error walking path "%s" - %e', path, err);
|
|
42
42
|
return badGatewayResponse(resource, 'Error walking path');
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"walk-path.js","sourceRoot":"","sources":["../../../src/utils/walk-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC/D,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAmBrE,KAAK,UAAU,QAAQ,CAAE,UAA2B,EAAE,IAAY,EAAE,OAA2B;IAC7F,MAAM,SAAS,GAAU,EAAE,CAAA;IAC3B,IAAI,eAAwC,CAAA;IAE5C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;QAClE,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACzB,eAAe,GAAG,KAAK,CAAA;IACzB,CAAC;IAED,IAAI,eAAe,IAAI,IAAI,EAAE,CAAC;QAC5B,MAAM,IAAI,iBAAiB,CAAC,2BAA2B,CAAC,CAAA;IAC1D,CAAC;IAED,OAAO;QACL,SAAS;QACT,eAAe;KAChB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAE,IAAiB;IAC7C,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAA;AAC/B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAA2D;IACjJ,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,UAAU,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,IAAI,IAAI,EAAE,EAAE,OAAO,CAAC,CAAA;IACzE,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,IAAI,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;YAC7B,MAAM,IAAI,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/C,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,yBAAyB,EAAE,eAAe,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnF,OAAO,gBAAgB,CAAC,QAAQ,CAAC,CAAA;QACnC,CAAC;QAED,GAAG,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"walk-path.js","sourceRoot":"","sources":["../../../src/utils/walk-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC/D,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAmBrE,KAAK,UAAU,QAAQ,CAAE,UAA2B,EAAE,IAAY,EAAE,OAA2B;IAC7F,MAAM,SAAS,GAAU,EAAE,CAAA;IAC3B,IAAI,eAAwC,CAAA;IAE5C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;QAClE,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACzB,eAAe,GAAG,KAAK,CAAA;IACzB,CAAC;IAED,IAAI,eAAe,IAAI,IAAI,EAAE,CAAC;QAC5B,MAAM,IAAI,iBAAiB,CAAC,2BAA2B,CAAC,CAAA;IAC1D,CAAC;IAED,OAAO;QACL,SAAS;QACT,eAAe;KAChB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAE,IAAiB;IAC7C,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAA;AAC/B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAA2D;IACjJ,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,UAAU,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,IAAI,IAAI,EAAE,EAAE,OAAO,CAAC,CAAA;IACzE,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,IAAI,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;YAC7B,MAAM,IAAI,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/C,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,yBAAyB,EAAE,eAAe,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnF,OAAO,gBAAgB,CAAC,QAAQ,CAAC,CAAA;QACnC,CAAC;QAED,GAAG,CAAC,KAAK,CAAC,8BAA8B,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;QACpD,OAAO,kBAAkB,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC"}
|
|
@@ -1,22 +1,16 @@
|
|
|
1
1
|
import type { CreateVerifiedFetchOptions, Resource, VerifiedFetchInit as VerifiedFetchOptions } from './index.js';
|
|
2
2
|
import type { Helia } from '@helia/interface';
|
|
3
|
-
import type { IPNS } from '@helia/ipns';
|
|
4
|
-
interface VerifiedFetchComponents {
|
|
5
|
-
helia: Helia;
|
|
6
|
-
ipns?: IPNS;
|
|
7
|
-
}
|
|
8
3
|
export declare class VerifiedFetch {
|
|
9
4
|
private readonly helia;
|
|
10
|
-
private readonly
|
|
5
|
+
private readonly ipnsResolver;
|
|
6
|
+
private readonly dnsLink;
|
|
11
7
|
private readonly log;
|
|
12
8
|
private readonly contentTypeParser;
|
|
13
9
|
private readonly blockstoreSessions;
|
|
14
|
-
private serverTimingHeaders;
|
|
15
10
|
private readonly withServerTiming;
|
|
16
11
|
private readonly plugins;
|
|
17
|
-
constructor(
|
|
12
|
+
constructor(helia: Helia, init?: CreateVerifiedFetchOptions);
|
|
18
13
|
private getBlockstore;
|
|
19
|
-
private handleServerTiming;
|
|
20
14
|
/**
|
|
21
15
|
* The last place a Response touches in verified-fetch before being returned to the user. This is where we add the
|
|
22
16
|
* Server-Timing header to the response if it has been collected. It should be used for any final processing of the
|
|
@@ -45,5 +39,4 @@ export declare class VerifiedFetch {
|
|
|
45
39
|
*/
|
|
46
40
|
stop(): Promise<void>;
|
|
47
41
|
}
|
|
48
|
-
export {};
|
|
49
42
|
//# sourceMappingURL=verified-fetch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verified-fetch.d.ts","sourceRoot":"","sources":["../../src/verified-fetch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verified-fetch.d.ts","sourceRoot":"","sources":["../../src/verified-fetch.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAgC,0BAA0B,EAAoB,QAAQ,EAAkB,iBAAiB,IAAI,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAIjL,OAAO,KAAK,EAAE,KAAK,EAAqB,MAAM,kBAAkB,CAAA;AA2BhE,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAO;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA+B;IACjE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqC;IACxE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;gBAEvC,KAAK,EAAE,KAAK,EAAE,IAAI,GAAE,0BAA+B;IAsDhE,OAAO,CAAC,aAAa;IAgBrB;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IA+F3B;;;OAGG;YACW,iBAAiB;IAgF/B;;;;;;OAMG;IACG,KAAK,CAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAwEhF;;OAEG;IACG,KAAK,IAAK,OAAO,CAAC,IAAI,CAAC;IAI7B;;OAEG;IACG,IAAI,IAAK,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dnsLink } from '@helia/dnslink';
|
|
2
|
+
import { ipnsResolver } from '@helia/ipns';
|
|
2
3
|
import { AbortError } from '@libp2p/interface';
|
|
3
4
|
import { prefixLogger } from '@libp2p/logger';
|
|
4
5
|
import { CustomProgressEvent } from 'progress-events';
|
|
@@ -12,17 +13,18 @@ import { IpnsRecordPlugin } from './plugins/plugin-handle-ipns-record.js';
|
|
|
12
13
|
import { JsonPlugin } from './plugins/plugin-handle-json.js';
|
|
13
14
|
import { RawPlugin } from './plugins/plugin-handle-raw.js';
|
|
14
15
|
import { TarPlugin } from './plugins/plugin-handle-tar.js';
|
|
16
|
+
import { URLResolver } from "./url-resolver.js";
|
|
15
17
|
import { contentTypeParser } from './utils/content-type-parser.js';
|
|
16
18
|
import { getContentDispositionFilename } from './utils/get-content-disposition-filename.js';
|
|
17
19
|
import { getETag } from './utils/get-e-tag.js';
|
|
18
20
|
import { getResolvedAcceptHeader } from './utils/get-resolved-accept-header.js';
|
|
19
21
|
import { getRedirectResponse } from './utils/handle-redirects.js';
|
|
20
|
-
import {
|
|
22
|
+
import { uriEncodeIPFSPath } from "./utils/ipfs-path-to-string.js";
|
|
21
23
|
import { resourceToSessionCacheKey } from './utils/resource-to-cache-key.js';
|
|
22
24
|
import { setCacheControlHeader } from './utils/response-headers.js';
|
|
23
25
|
import { badRequestResponse, notAcceptableResponse, notSupportedResponse, badGatewayResponse } from './utils/responses.js';
|
|
24
26
|
import { selectOutputType } from './utils/select-output-type.js';
|
|
25
|
-
import {
|
|
27
|
+
import { ServerTiming } from './utils/server-timing.js';
|
|
26
28
|
const SESSION_CACHE_MAX_SIZE = 100;
|
|
27
29
|
const SESSION_CACHE_TTL_MS = 60 * 1000;
|
|
28
30
|
function convertOptions(options) {
|
|
@@ -43,18 +45,19 @@ function convertOptions(options) {
|
|
|
43
45
|
}
|
|
44
46
|
export class VerifiedFetch {
|
|
45
47
|
helia;
|
|
46
|
-
|
|
48
|
+
ipnsResolver;
|
|
49
|
+
dnsLink;
|
|
47
50
|
log;
|
|
48
51
|
contentTypeParser;
|
|
49
52
|
blockstoreSessions;
|
|
50
|
-
serverTimingHeaders = [];
|
|
51
53
|
withServerTiming;
|
|
52
54
|
plugins = [];
|
|
53
|
-
constructor(
|
|
55
|
+
constructor(helia, init = {}) {
|
|
54
56
|
this.helia = helia;
|
|
55
57
|
this.log = helia.logger.forComponent('helia:verified-fetch');
|
|
56
|
-
this.
|
|
57
|
-
this.
|
|
58
|
+
this.ipnsResolver = init.ipnsResolver ?? ipnsResolver(helia);
|
|
59
|
+
this.dnsLink = init.dnsLink ?? dnsLink(helia);
|
|
60
|
+
this.contentTypeParser = init.contentTypeParser ?? contentTypeParser;
|
|
58
61
|
this.blockstoreSessions = new QuickLRU({
|
|
59
62
|
maxSize: init?.sessionCacheSize ?? SESSION_CACHE_MAX_SIZE,
|
|
60
63
|
maxAge: init?.sessionTTLms ?? SESSION_CACHE_TTL_MS,
|
|
@@ -67,9 +70,9 @@ export class VerifiedFetch {
|
|
|
67
70
|
...init,
|
|
68
71
|
logger: prefixLogger('helia:verified-fetch'),
|
|
69
72
|
getBlockstore: (cid, resource, useSession, options) => this.getBlockstore(cid, resource, useSession, options),
|
|
70
|
-
handleServerTiming: async (name, description, fn) => this.handleServerTiming(name, description, fn, this.withServerTiming),
|
|
71
73
|
helia,
|
|
72
|
-
contentTypeParser: this.contentTypeParser
|
|
74
|
+
contentTypeParser: this.contentTypeParser,
|
|
75
|
+
ipnsResolver: this.ipnsResolver
|
|
73
76
|
};
|
|
74
77
|
const defaultPlugins = [
|
|
75
78
|
new DagWalkPlugin(pluginOptions),
|
|
@@ -82,7 +85,7 @@ export class VerifiedFetch {
|
|
|
82
85
|
new DagCborPlugin(pluginOptions),
|
|
83
86
|
new DagPbPlugin(pluginOptions)
|
|
84
87
|
];
|
|
85
|
-
const customPlugins = init
|
|
88
|
+
const customPlugins = init.plugins?.map((pluginFactory) => pluginFactory(pluginOptions)) ?? [];
|
|
86
89
|
if (customPlugins.length > 0) {
|
|
87
90
|
// allow custom plugins to replace default plugins
|
|
88
91
|
const defaultPluginMap = new Map(defaultPlugins.map(plugin => [plugin.id, plugin]));
|
|
@@ -108,32 +111,19 @@ export class VerifiedFetch {
|
|
|
108
111
|
}
|
|
109
112
|
return session;
|
|
110
113
|
}
|
|
111
|
-
async handleServerTiming(name, description, fn, withServerTiming) {
|
|
112
|
-
if (!withServerTiming) {
|
|
113
|
-
return fn();
|
|
114
|
-
}
|
|
115
|
-
const { error, result, header } = await serverTiming(name, description, fn);
|
|
116
|
-
this.serverTimingHeaders.push(header);
|
|
117
|
-
if (error != null) {
|
|
118
|
-
throw error;
|
|
119
|
-
}
|
|
120
|
-
return result;
|
|
121
|
-
}
|
|
122
114
|
/**
|
|
123
115
|
* The last place a Response touches in verified-fetch before being returned to the user. This is where we add the
|
|
124
116
|
* Server-Timing header to the response if it has been collected. It should be used for any final processing of the
|
|
125
117
|
* response before it is returned to the user.
|
|
126
118
|
*/
|
|
127
|
-
handleFinalResponse(response,
|
|
128
|
-
if (this.
|
|
129
|
-
|
|
130
|
-
response.headers.set('Server-Timing', headerString);
|
|
131
|
-
this.serverTimingHeaders = [];
|
|
119
|
+
handleFinalResponse(response, context) {
|
|
120
|
+
if ((this.withServerTiming || context?.withServerTiming === true) && context?.serverTiming != null) {
|
|
121
|
+
response.headers.set('Server-Timing', context?.serverTiming.getHeader());
|
|
132
122
|
}
|
|
133
123
|
// if there are multiple ranges, we should omit the content-length header. see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Transfer-Encoding
|
|
134
124
|
if (response.headers.get('Transfer-Encoding') !== 'chunked') {
|
|
135
|
-
if (byteRangeContext != null) {
|
|
136
|
-
const contentLength = byteRangeContext.getLength();
|
|
125
|
+
if (context?.byteRangeContext != null) {
|
|
126
|
+
const contentLength = context.byteRangeContext.getLength();
|
|
137
127
|
if (contentLength != null) {
|
|
138
128
|
this.log.trace('Setting Content-Length from byteRangeContext: %d', contentLength);
|
|
139
129
|
response.headers.set('Content-Length', contentLength.toString());
|
|
@@ -144,18 +134,18 @@ export class VerifiedFetch {
|
|
|
144
134
|
let contentDisposition;
|
|
145
135
|
this.log.trace('checking for content disposition');
|
|
146
136
|
// force download if requested
|
|
147
|
-
if (query?.download === true) {
|
|
137
|
+
if (context?.query?.download === true) {
|
|
148
138
|
contentDisposition = 'attachment';
|
|
149
139
|
}
|
|
150
140
|
else {
|
|
151
141
|
this.log.trace('download not requested');
|
|
152
142
|
}
|
|
153
143
|
// override filename if requested
|
|
154
|
-
if (query?.filename != null) {
|
|
144
|
+
if (context?.query?.filename != null) {
|
|
155
145
|
if (contentDisposition == null) {
|
|
156
146
|
contentDisposition = 'inline';
|
|
157
147
|
}
|
|
158
|
-
contentDisposition = `${contentDisposition}; ${getContentDispositionFilename(query.filename)}`;
|
|
148
|
+
contentDisposition = `${contentDisposition}; ${getContentDispositionFilename(context.query.filename)}`;
|
|
159
149
|
}
|
|
160
150
|
else {
|
|
161
151
|
this.log.trace('no filename specified in query');
|
|
@@ -166,21 +156,29 @@ export class VerifiedFetch {
|
|
|
166
156
|
else {
|
|
167
157
|
this.log.trace('no content disposition specified');
|
|
168
158
|
}
|
|
169
|
-
if (cid != null && response.headers.get('etag') == null) {
|
|
170
|
-
response.headers.set('etag', getETag({
|
|
159
|
+
if (context?.cid != null && response.headers.get('etag') == null) {
|
|
160
|
+
response.headers.set('etag', getETag({
|
|
161
|
+
cid: context.pathDetails?.terminalElement.cid ?? context.cid,
|
|
162
|
+
reqFormat: context.reqFormat,
|
|
163
|
+
weak: false
|
|
164
|
+
}));
|
|
171
165
|
}
|
|
172
|
-
if (protocol != null) {
|
|
173
|
-
setCacheControlHeader({
|
|
166
|
+
if (context?.protocol != null && context.ttl != null) {
|
|
167
|
+
setCacheControlHeader({
|
|
168
|
+
response,
|
|
169
|
+
ttl: context.ttl,
|
|
170
|
+
protocol: context.protocol
|
|
171
|
+
});
|
|
174
172
|
}
|
|
175
|
-
if (ipfsPath != null) {
|
|
176
|
-
response.headers.set('X-Ipfs-Path', ipfsPath);
|
|
173
|
+
if (context?.ipfsPath != null) {
|
|
174
|
+
response.headers.set('X-Ipfs-Path', uriEncodeIPFSPath(context.ipfsPath));
|
|
177
175
|
}
|
|
178
176
|
// set CORS headers. If hosting your own gateway with verified-fetch behind the scenes, you can alter these before you send the response to the client.
|
|
179
177
|
response.headers.set('Access-Control-Allow-Origin', '*');
|
|
180
178
|
response.headers.set('Access-Control-Allow-Methods', 'GET, HEAD, OPTIONS');
|
|
181
179
|
response.headers.set('Access-Control-Allow-Headers', 'Range, X-Requested-With');
|
|
182
|
-
response.headers.set('Access-Control-Expose-Headers', 'Content-Range, Content-Length, X-Ipfs-Path, X-Stream-Output');
|
|
183
|
-
if (reqFormat !== 'car') {
|
|
180
|
+
response.headers.set('Access-Control-Expose-Headers', 'Content-Range, Content-Length, X-Ipfs-Path, X-Ipfs-Roots, X-Stream-Output');
|
|
181
|
+
if (context?.reqFormat !== 'car') {
|
|
184
182
|
// if we are not doing streaming responses, set the Accept-Ranges header to bytes to enable range requests
|
|
185
183
|
response.headers.set('Accept-Ranges', 'bytes');
|
|
186
184
|
}
|
|
@@ -188,10 +186,16 @@ export class VerifiedFetch {
|
|
|
188
186
|
// set accept-ranges to none to disable range requests for streaming responses
|
|
189
187
|
response.headers.set('Accept-Ranges', 'none');
|
|
190
188
|
}
|
|
191
|
-
if (
|
|
189
|
+
if (response.headers.get('Content-Type')?.includes('application/vnd.ipld.car') === true || response.headers.get('Content-Type')?.includes('application/vnd.ipld.raw') === true) {
|
|
190
|
+
// see https://specs.ipfs.tech/http-gateways/path-gateway/#x-content-type-options-response-header
|
|
191
|
+
response.headers.set('X-Content-Type-Options', 'nosniff');
|
|
192
|
+
}
|
|
193
|
+
if (context?.options?.method === 'HEAD') {
|
|
192
194
|
// don't send the body for HEAD requests
|
|
193
|
-
|
|
194
|
-
|
|
195
|
+
return new Response(null, {
|
|
196
|
+
status: 200,
|
|
197
|
+
headers: response.headers
|
|
198
|
+
});
|
|
195
199
|
}
|
|
196
200
|
return response;
|
|
197
201
|
}
|
|
@@ -205,28 +209,28 @@ export class VerifiedFetch {
|
|
|
205
209
|
const pluginsUsed = new Set();
|
|
206
210
|
let prevModificationId = context.modified;
|
|
207
211
|
while (passCount < maxPasses) {
|
|
208
|
-
this.log(`
|
|
212
|
+
this.log(`starting pipeline pass #${passCount + 1}`);
|
|
209
213
|
passCount++;
|
|
210
214
|
// gather plugins that say they can handle the *current* context, but haven't been used yet
|
|
211
215
|
const readyPlugins = this.plugins.filter(p => !pluginsUsed.has(p.id)).filter(p => p.canHandle(context));
|
|
212
216
|
if (readyPlugins.length === 0) {
|
|
213
|
-
this.log.trace('
|
|
217
|
+
this.log.trace('no plugins can handle the current context.. checking by CID code');
|
|
214
218
|
const plugins = this.plugins.filter(p => p.codes.includes(context.cid.code));
|
|
215
219
|
if (plugins.length > 0) {
|
|
216
220
|
readyPlugins.push(...plugins);
|
|
217
221
|
}
|
|
218
222
|
else {
|
|
219
|
-
this.log.trace('
|
|
223
|
+
this.log.trace('no plugins found that can handle request by CID code; exiting pipeline.');
|
|
220
224
|
break;
|
|
221
225
|
}
|
|
222
226
|
}
|
|
223
|
-
this.log.trace('
|
|
227
|
+
this.log.trace('plugins ready to handle request: ', readyPlugins.map(p => p.id).join(', '));
|
|
224
228
|
// track if any plugin changed the context or returned a response
|
|
225
229
|
let contextChanged = false;
|
|
226
230
|
let pluginHandled = false;
|
|
227
231
|
for (const plugin of readyPlugins) {
|
|
228
232
|
try {
|
|
229
|
-
this.log.trace('
|
|
233
|
+
this.log.trace('invoking plugin:', plugin.id);
|
|
230
234
|
pluginsUsed.add(plugin.id);
|
|
231
235
|
const maybeResponse = await plugin.handle(context);
|
|
232
236
|
if (maybeResponse != null) {
|
|
@@ -240,7 +244,7 @@ export class VerifiedFetch {
|
|
|
240
244
|
if (context.options?.signal?.aborted) {
|
|
241
245
|
throw new AbortError(context.options?.signal?.reason);
|
|
242
246
|
}
|
|
243
|
-
this.log.error('
|
|
247
|
+
this.log.error('error in plugin %s - %e', plugin.constructor.name, err);
|
|
244
248
|
// if fatal, short-circuit the pipeline
|
|
245
249
|
if (err.name === 'PluginFatalError') {
|
|
246
250
|
// if plugin provides a custom error response, return it
|
|
@@ -256,7 +260,7 @@ export class VerifiedFetch {
|
|
|
256
260
|
}
|
|
257
261
|
}
|
|
258
262
|
if (finalResponse != null) {
|
|
259
|
-
this.log.trace('
|
|
263
|
+
this.log.trace('plugin %s produced final response', plugin.id);
|
|
260
264
|
break;
|
|
261
265
|
}
|
|
262
266
|
}
|
|
@@ -264,7 +268,7 @@ export class VerifiedFetch {
|
|
|
264
268
|
break;
|
|
265
269
|
}
|
|
266
270
|
if (!contextChanged) {
|
|
267
|
-
this.log.trace('
|
|
271
|
+
this.log.trace('no context changes and no final response; exiting pipeline.');
|
|
268
272
|
break;
|
|
269
273
|
}
|
|
270
274
|
}
|
|
@@ -283,12 +287,16 @@ export class VerifiedFetch {
|
|
|
283
287
|
return this.handleFinalResponse(new Response(null, { status: 200 }));
|
|
284
288
|
}
|
|
285
289
|
const options = convertOptions(opts);
|
|
286
|
-
const
|
|
290
|
+
const serverTiming = new ServerTiming();
|
|
291
|
+
const urlResolver = new URLResolver({
|
|
292
|
+
ipnsResolver: this.ipnsResolver,
|
|
293
|
+
dnsLink: this.dnsLink,
|
|
294
|
+
timing: serverTiming
|
|
295
|
+
});
|
|
287
296
|
options?.onProgress?.(new CustomProgressEvent('verified-fetch:request:start', { resource }));
|
|
288
297
|
let parsedResult;
|
|
289
298
|
try {
|
|
290
|
-
parsedResult = await
|
|
291
|
-
this.serverTimingHeaders.push(...parsedResult.serverTimings.map(({ header }) => header));
|
|
299
|
+
parsedResult = await urlResolver.resolve(resource, options);
|
|
292
300
|
}
|
|
293
301
|
catch (err) {
|
|
294
302
|
if (options?.signal?.aborted) {
|
|
@@ -302,9 +310,10 @@ export class VerifiedFetch {
|
|
|
302
310
|
const accept = selectOutputType(parsedResult.cid, acceptHeader);
|
|
303
311
|
this.log('output type %s', accept);
|
|
304
312
|
if (acceptHeader != null && accept == null) {
|
|
313
|
+
this.log.error('could not fulfil request based on accept header');
|
|
305
314
|
return this.handleFinalResponse(notAcceptableResponse(resource.toString()));
|
|
306
315
|
}
|
|
307
|
-
const responseContentType = accept?.split(';')[0] ?? 'application/octet-stream';
|
|
316
|
+
const responseContentType = accept?.mimeType.split(';')[0] ?? 'application/octet-stream';
|
|
308
317
|
const redirectResponse = await getRedirectResponse({ resource, options, logger: this.helia.logger, cid: parsedResult.cid });
|
|
309
318
|
if (redirectResponse != null) {
|
|
310
319
|
return this.handleFinalResponse(redirectResponse);
|
|
@@ -314,10 +323,12 @@ export class VerifiedFetch {
|
|
|
314
323
|
resource: resource.toString(),
|
|
315
324
|
accept,
|
|
316
325
|
options,
|
|
317
|
-
withServerTiming,
|
|
318
326
|
onProgress: options?.onProgress,
|
|
319
327
|
modified: 0,
|
|
320
|
-
plugins: this.plugins.map(p => p.id)
|
|
328
|
+
plugins: this.plugins.map(p => p.id),
|
|
329
|
+
query: parsedResult.query ?? {},
|
|
330
|
+
withServerTiming: Boolean(options?.withServerTiming) || Boolean(this.withServerTiming),
|
|
331
|
+
serverTiming
|
|
321
332
|
};
|
|
322
333
|
this.log.trace('finding handler for cid code "%s" and response content type "%s"', parsedResult.cid.code, responseContentType);
|
|
323
334
|
const response = await this.runPluginPipeline(context);
|