@helia/verified-fetch 1.4.1 → 1.4.3
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 +8 -8
- package/dist/src/types.d.ts +23 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +2 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/handle-redirects.d.ts +16 -0
- package/dist/src/utils/handle-redirects.d.ts.map +1 -0
- package/dist/src/utils/handle-redirects.js +85 -0
- package/dist/src/utils/handle-redirects.js.map +1 -0
- package/dist/src/utils/parse-url-string.js +1 -1
- package/dist/src/utils/parse-url-string.js.map +1 -1
- package/dist/src/utils/response-headers.d.ts +7 -0
- package/dist/src/utils/response-headers.d.ts.map +1 -1
- package/dist/src/utils/response-headers.js +10 -0
- package/dist/src/utils/response-headers.js.map +1 -1
- package/dist/src/utils/walk-path.d.ts +13 -0
- package/dist/src/utils/walk-path.d.ts.map +1 -1
- package/dist/src/utils/walk-path.js +22 -0
- package/dist/src/utils/walk-path.js.map +1 -1
- package/dist/src/verified-fetch.d.ts.map +1 -1
- package/dist/src/verified-fetch.js +53 -58
- package/dist/src/verified-fetch.js.map +1 -1
- package/dist/typedoc-urls.json +25 -25
- package/package.json +22 -22
- package/src/types.ts +29 -0
- package/src/utils/handle-redirects.ts +101 -0
- package/src/utils/parse-url-string.ts +1 -1
- package/src/utils/response-headers.ts +13 -0
- package/src/utils/walk-path.ts +24 -1
- package/src/verified-fetch.ts +58 -94
package/dist/src/types.d.ts
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
import { type AbortOptions } from '@libp2p/interface';
|
|
2
|
+
import { type CID } from 'multiformats/cid';
|
|
3
|
+
import type { VerifiedFetchInit } from './index.js';
|
|
1
4
|
export type RequestFormatShorthand = 'raw' | 'car' | 'tar' | 'ipns-record' | 'dag-json' | 'dag-cbor' | 'json' | 'cbor';
|
|
2
5
|
export type SupportedBodyTypes = string | ArrayBuffer | Blob | ReadableStream<Uint8Array> | null;
|
|
6
|
+
export interface FetchHandlerFunctionArg {
|
|
7
|
+
cid: CID;
|
|
8
|
+
path: string;
|
|
9
|
+
/**
|
|
10
|
+
* Whether to use a session during fetch operations
|
|
11
|
+
*
|
|
12
|
+
* @default true
|
|
13
|
+
*/
|
|
14
|
+
session: boolean;
|
|
15
|
+
options?: Omit<VerifiedFetchInit, 'signal'> & AbortOptions;
|
|
16
|
+
/**
|
|
17
|
+
* If present, the user has sent an accept header with this value - if the
|
|
18
|
+
* content cannot be represented in this format a 406 should be returned
|
|
19
|
+
*/
|
|
20
|
+
accept?: string;
|
|
21
|
+
/**
|
|
22
|
+
* The originally requested resource
|
|
23
|
+
*/
|
|
24
|
+
resource: string;
|
|
25
|
+
}
|
|
3
26
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,aAAa,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;AAEtH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,WAAW,GAAG,IAAI,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAA"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD,MAAM,MAAM,sBAAsB,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,aAAa,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;AAEtH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,WAAW,GAAG,IAAI,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAA;AAEhG,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,GAAG,CAAA;IACR,IAAI,EAAE,MAAM,CAAA;IAEZ;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAA;IAEhB,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,GAAG,YAAY,CAAA;IAE1D;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;CACjB"}
|
package/dist/src/types.js
CHANGED
package/dist/src/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAY,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type AbortOptions, type ComponentLogger } from '@libp2p/interface';
|
|
2
|
+
import { type VerifiedFetchInit, type Resource } from '../index.js';
|
|
3
|
+
import type { CID } from 'multiformats/cid';
|
|
4
|
+
interface GetRedirectResponse {
|
|
5
|
+
cid: CID;
|
|
6
|
+
resource: Resource;
|
|
7
|
+
options?: Omit<VerifiedFetchInit, 'signal'> & AbortOptions;
|
|
8
|
+
logger: ComponentLogger;
|
|
9
|
+
/**
|
|
10
|
+
* Only used in testing.
|
|
11
|
+
*/
|
|
12
|
+
fetch?: typeof globalThis.fetch;
|
|
13
|
+
}
|
|
14
|
+
export declare function getRedirectResponse({ resource, options, logger, cid, fetch }: GetRedirectResponse): Promise<null | Response>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=handle-redirects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle-redirects.d.ts","sourceRoot":"","sources":["../../../src/utils/handle-redirects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAA;AAGnE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAE3C,UAAU,mBAAmB;IAC3B,GAAG,EAAE,GAAG,CAAA;IACR,QAAQ,EAAE,QAAQ,CAAA;IAClB,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,GAAG,YAAY,CAAA;IAC1D,MAAM,EAAE,eAAe,CAAA;IAEvB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;CAChC;AAWD,wBAAsB,mBAAmB,CAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,KAAwB,EAAE,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,CAyEtJ"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {} from '@libp2p/interface';
|
|
2
|
+
import {} from '../index.js';
|
|
3
|
+
import { matchURLString } from './parse-url-string.js';
|
|
4
|
+
import { movedPermanentlyResponse } from './responses.js';
|
|
5
|
+
function maybeAddTraillingSlash(path) {
|
|
6
|
+
// if it has an extension-like ending, don't add a trailing slash
|
|
7
|
+
if (path.match(/\.[a-zA-Z0-9]{1,4}$/) != null) {
|
|
8
|
+
return path;
|
|
9
|
+
}
|
|
10
|
+
return path.endsWith('/') ? path : `${path}/`;
|
|
11
|
+
}
|
|
12
|
+
// See https://specs.ipfs.tech/http-gateways/path-gateway/#location-response-header
|
|
13
|
+
export async function getRedirectResponse({ resource, options, logger, cid, fetch = globalThis.fetch }) {
|
|
14
|
+
const log = logger.forComponent('helia:verified-fetch:get-redirect-response');
|
|
15
|
+
if (typeof resource !== 'string' || options == null || ['ipfs://', 'ipns://'].some((prefix) => resource.startsWith(prefix))) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const headers = new Headers(options?.headers);
|
|
19
|
+
const forwardedHost = headers.get('x-forwarded-host');
|
|
20
|
+
const headerHost = headers.get('host');
|
|
21
|
+
const forwardedFor = headers.get('x-forwarded-for');
|
|
22
|
+
if (forwardedFor == null && forwardedHost == null && headerHost == null) {
|
|
23
|
+
log.trace('no redirect info found in headers');
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
log.trace('checking for redirect info');
|
|
27
|
+
// if x-forwarded-host is passed, we need to set the location header to the subdomain
|
|
28
|
+
// so that the browser can redirect to the correct subdomain
|
|
29
|
+
try {
|
|
30
|
+
const urlParts = matchURLString(resource);
|
|
31
|
+
const reqUrl = new URL(resource);
|
|
32
|
+
const actualHost = forwardedHost ?? reqUrl.host;
|
|
33
|
+
const subdomainUrl = new URL(reqUrl);
|
|
34
|
+
if (urlParts.protocol === 'ipfs' && cid.version === 0) {
|
|
35
|
+
subdomainUrl.host = `${cid.toV1()}.ipfs.${actualHost}`;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
subdomainUrl.host = `${urlParts.cidOrPeerIdOrDnsLink}.${urlParts.protocol}.${actualHost}`;
|
|
39
|
+
}
|
|
40
|
+
if (headerHost?.includes(urlParts.protocol) === true && subdomainUrl.host.includes(headerHost)) {
|
|
41
|
+
log.trace('request was for a subdomain already, not setting location header');
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
if (headerHost != null && !subdomainUrl.host.includes(headerHost)) {
|
|
45
|
+
log.trace('host header is not the same as the subdomain url host, not setting location header');
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
if (reqUrl.host === subdomainUrl.host) {
|
|
49
|
+
log.trace('req url is the same as the subdomain url, not setting location header');
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
subdomainUrl.pathname = maybeAddTraillingSlash(reqUrl.pathname.replace(`/${urlParts.cidOrPeerIdOrDnsLink}`, '').replace(`/${urlParts.protocol}`, ''));
|
|
53
|
+
log.trace('subdomain url %s', subdomainUrl.href);
|
|
54
|
+
const pathUrl = new URL(reqUrl, `${reqUrl.protocol}//${actualHost}`);
|
|
55
|
+
pathUrl.pathname = maybeAddTraillingSlash(reqUrl.pathname);
|
|
56
|
+
log.trace('path url %s', pathUrl.href);
|
|
57
|
+
// try to query subdomain with HEAD request to see if it's supported
|
|
58
|
+
try {
|
|
59
|
+
const subdomainTest = await fetch(subdomainUrl, { method: 'HEAD' });
|
|
60
|
+
if (subdomainTest.ok) {
|
|
61
|
+
log('subdomain supported, redirecting to subdomain');
|
|
62
|
+
return movedPermanentlyResponse(resource.toString(), subdomainUrl.href);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
log('subdomain not supported, subdomain failed with status %s %s', subdomainTest.status, subdomainTest.statusText);
|
|
66
|
+
throw new Error('subdomain not supported');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
log('subdomain not supported', err);
|
|
71
|
+
if (pathUrl.href === reqUrl.href) {
|
|
72
|
+
log('path url is the same as the request url, not setting location header');
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
// pathUrl is different from request URL (maybe even with just a trailing slash)
|
|
76
|
+
return movedPermanentlyResponse(resource.toString(), pathUrl.href);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
// if it's not a full URL, we have nothing left to do.
|
|
81
|
+
log.error('error setting location header for x-forwarded-host', e);
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=handle-redirects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle-redirects.js","sourceRoot":"","sources":["../../../src/utils/handle-redirects.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,7 +21,7 @@ function matchUrlGroupsGuard(groups) {
|
|
|
21
21
|
(queryString == null || typeof queryString === 'string');
|
|
22
22
|
}
|
|
23
23
|
export function matchURLString(urlString) {
|
|
24
|
-
for (const pattern of [
|
|
24
|
+
for (const pattern of [SUBDOMAIN_GATEWAY_REGEX, URL_REGEX, PATH_GATEWAY_REGEX, PATH_REGEX]) {
|
|
25
25
|
const match = urlString.match(pattern);
|
|
26
26
|
if (matchUrlGroupsGuard(match?.groups)) {
|
|
27
27
|
return match.groups;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-url-string.js","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAMhC,MAAM,SAAS,GAAG,IAAI,IAAI,CAA2C,IAAI,CAAC,CAAA;AAuC1E,MAAM,SAAS,GAAG,kGAAkG,CAAA;AACpH,MAAM,UAAU,GAAG,iGAAiG,CAAA;AACpH,MAAM,kBAAkB,GAAG,oHAAoH,CAAA;AAC/I,MAAM,uBAAuB,GAAG,oHAAoH,CAAA;AASpJ,SAAS,mBAAmB,CAAE,MAA6D;IACzF,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,CAAA;IACjC,IAAI,QAAQ,IAAI,IAAI;QAAE,OAAO,KAAK,CAAA;IAClC,MAAM,oBAAoB,GAAG,MAAM,EAAE,oBAAoB,CAAA;IACzD,IAAI,oBAAoB,IAAI,IAAI;QAAE,OAAO,KAAK,CAAA;IAC9C,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,CAAA;IACzB,MAAM,WAAW,GAAG,MAAM,EAAE,WAAW,CAAA;IAEvC,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,WAAW,IAAI,IAAI,IAAI,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAA;AAC5D,CAAC;AAED,MAAM,UAAU,cAAc,CAAE,SAAiB;IAC/C,KAAK,MAAM,OAAO,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"parse-url-string.js","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CID } from 'multiformats/cid';
|
|
1
2
|
interface CacheControlHeaderOptions {
|
|
2
3
|
/**
|
|
3
4
|
* This should be seconds as a number.
|
|
@@ -27,5 +28,11 @@ export declare function getContentRangeHeader({ byteStart, byteEnd, byteSize }:
|
|
|
27
28
|
byteEnd: number | undefined;
|
|
28
29
|
byteSize: number | undefined;
|
|
29
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;
|
|
30
37
|
export {};
|
|
31
38
|
//# 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":"AAAA,UAAU,yBAAyB;IACjC;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,yBAAyB,GAAG,IAAI,CAgBnG;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"}
|
|
1
|
+
{"version":3,"file":"response-headers.d.ts","sourceRoot":"","sources":["../../../src/utils/response-headers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAE3C,UAAU,yBAAyB;IACjC;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,yBAAyB,GAAG,IAAI,CAgBnG;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"}
|
|
@@ -59,4 +59,14 @@ export function getContentRangeHeader({ byteStart, byteEnd, byteSize }) {
|
|
|
59
59
|
}
|
|
60
60
|
return `bytes ${byteStart}-${byteEnd}/${total}`;
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Sets the `X-Ipfs-Roots` header on the response if it exists.
|
|
64
|
+
*
|
|
65
|
+
* @see https://specs.ipfs.tech/http-gateways/path-gateway/#x-ipfs-roots-response-header
|
|
66
|
+
*/
|
|
67
|
+
export function setIpfsRoots(response, ipfsRoots) {
|
|
68
|
+
if (ipfsRoots != null) {
|
|
69
|
+
response.headers.set('X-Ipfs-Roots', ipfsRoots.map(cid => cid.toV1().toString()).join(','));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
62
72
|
//# sourceMappingURL=response-headers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-headers.js","sourceRoot":"","sources":["../../../src/utils/response-headers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"response-headers.js","sourceRoot":"","sources":["../../../src/utils/response-headers.ts"],"names":[],"mappings":"AAaA;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAA6B;IAC3F,IAAI,WAAmB,CAAA;IACvB,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,WAAW,GAAG,qCAAqC,CAAA;IACrD,CAAC;SAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB;;;;WAIG;QACH,WAAW,GAAG,qBAAqB,CAAA;IACrC,CAAC;SAAM,CAAC;QACN,WAAW,GAAG,mBAAmB,GAAG,EAAE,CAAA;IACxC,CAAC;IAED,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,WAAW,CAAC,CAAA;AACpD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAE,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAgG;IACnK,MAAM,KAAK,GAAG,QAAQ,IAAI,GAAG,CAAA,CAAC,mDAAmD;IAEjF,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,kFAAkF,CAAC,CAAA;IACrG,CAAC;IACD,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,oFAAoF,CAAC,CAAA;IACvG,CAAC;IAED,IAAI,SAAS,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACzC,0BAA0B;QAC1B,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YACrB,OAAO,WAAW,KAAK,EAAE,CAAA;QAC3B,CAAC;QACD,OAAO,SAAS,SAAS,IAAI,QAAQ,GAAG,CAAC,IAAI,QAAQ,EAAE,CAAA;IACzD,CAAC;IAED,IAAI,SAAS,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACzC,wBAAwB;QACxB,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YACrB,OAAO,WAAW,KAAK,EAAE,CAAA;QAC3B,CAAC;QACD,MAAM,GAAG,GAAG,QAAQ,GAAG,CAAC,CAAA;QACxB,MAAM,KAAK,GAAG,GAAG,GAAG,OAAO,GAAG,CAAC,CAAA;QAE/B,OAAO,SAAS,KAAK,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAA;IAC5C,CAAC;IAED,IAAI,SAAS,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACzC,uDAAuD;QACvD,OAAO,WAAW,KAAK,EAAE,CAAA;IAC3B,CAAC;IAED,OAAO,SAAS,SAAS,IAAI,OAAO,IAAI,KAAK,EAAE,CAAA;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAE,QAAkB,EAAE,SAAiB;IACjE,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;QACtB,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IAC7F,CAAC;AACH,CAAC"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { type Logger } from '@libp2p/interface';
|
|
2
|
+
import { type Blockstore } from 'interface-blockstore';
|
|
1
3
|
import { type ExporterOptions, type ReadableStorage, type ObjectNode, type UnixFSEntry } from 'ipfs-unixfs-exporter';
|
|
4
|
+
import { type FetchHandlerFunctionArg } from '../types.js';
|
|
2
5
|
import type { CID } from 'multiformats/cid';
|
|
3
6
|
export interface PathWalkerOptions extends ExporterOptions {
|
|
4
7
|
}
|
|
@@ -11,4 +14,14 @@ export interface PathWalkerFn {
|
|
|
11
14
|
}
|
|
12
15
|
export declare function walkPath(blockstore: ReadableStorage, path: string, options?: PathWalkerOptions): Promise<PathWalkerResponse>;
|
|
13
16
|
export declare function isObjectNode(node: UnixFSEntry): node is ObjectNode;
|
|
17
|
+
/**
|
|
18
|
+
* Attempts to walk the path in the blockstore, returning ipfsRoots needed to resolve the path, and the terminal element.
|
|
19
|
+
* If the signal is aborted, the function will throw an AbortError
|
|
20
|
+
* If a terminal element is not found, a notFoundResponse is returned
|
|
21
|
+
* If another unknown error occurs, a badGatewayResponse is returned
|
|
22
|
+
*/
|
|
23
|
+
export declare function handlePathWalking({ cid, path, resource, options, blockstore, log }: Omit<FetchHandlerFunctionArg, 'session'> & {
|
|
24
|
+
blockstore: Blockstore;
|
|
25
|
+
log: Logger;
|
|
26
|
+
}): Promise<PathWalkerResponse | Response>;
|
|
14
27
|
//# sourceMappingURL=walk-path.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"walk-path.d.ts","sourceRoot":"","sources":["../../../src/utils/walk-path.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"walk-path.d.ts","sourceRoot":"","sources":["../../../src/utils/walk-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAA4B,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAC9I,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAE1D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAE3C,MAAM,WAAW,iBAAkB,SAAQ,eAAe;CAEzD;AACD,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,GAAG,EAAE,CAAA;IAChB,eAAe,EAAE,WAAW,CAAA;CAE7B;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,UAAU,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;CACtG;AAED,wBAAsB,QAAQ,CAAE,UAAU,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAiBnI;AAED,wBAAgB,YAAY,CAAE,IAAI,EAAE,WAAW,GAAG,IAAI,IAAI,UAAU,CAEnE;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC,uBAAuB,EAAE,SAAS,CAAC,GAAG;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,kBAAkB,GAAG,QAAQ,CAAC,CAYtN"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { CodeError } from '@libp2p/interface';
|
|
2
|
+
import {} from 'interface-blockstore';
|
|
2
3
|
import { walkPath as exporterWalk } from 'ipfs-unixfs-exporter';
|
|
4
|
+
import {} from '../types.js';
|
|
5
|
+
import { badGatewayResponse, notFoundResponse } from './responses.js';
|
|
3
6
|
export async function walkPath(blockstore, path, options) {
|
|
4
7
|
const ipfsRoots = [];
|
|
5
8
|
let terminalElement;
|
|
@@ -18,4 +21,23 @@ export async function walkPath(blockstore, path, options) {
|
|
|
18
21
|
export function isObjectNode(node) {
|
|
19
22
|
return node.type === 'object';
|
|
20
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Attempts to walk the path in the blockstore, returning ipfsRoots needed to resolve the path, and the terminal element.
|
|
26
|
+
* If the signal is aborted, the function will throw an AbortError
|
|
27
|
+
* If a terminal element is not found, a notFoundResponse is returned
|
|
28
|
+
* If another unknown error occurs, a badGatewayResponse is returned
|
|
29
|
+
*/
|
|
30
|
+
export async function handlePathWalking({ cid, path, resource, options, blockstore, log }) {
|
|
31
|
+
try {
|
|
32
|
+
return await walkPath(blockstore, `${cid.toString()}/${path}`, options);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
options?.signal?.throwIfAborted();
|
|
36
|
+
if (['ERR_NO_PROP', 'ERR_NO_TERMINAL_ELEMENT', 'ERR_NOT_FOUND'].includes(err.code)) {
|
|
37
|
+
return notFoundResponse(resource);
|
|
38
|
+
}
|
|
39
|
+
log.error('error walking path %s', path, err);
|
|
40
|
+
return badGatewayResponse(resource, 'Error walking path');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
21
43
|
//# sourceMappingURL=walk-path.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"walk-path.js","sourceRoot":"","sources":["../../../src/utils/walk-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"walk-path.js","sourceRoot":"","sources":["../../../src/utils/walk-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAe,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAmB,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAiF,MAAM,sBAAsB,CAAA;AAC9I,OAAO,EAAgC,MAAM,aAAa,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAgBrE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAE,UAA2B,EAAE,IAAY,EAAE,OAA2B;IACpG,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,SAAS,CAAC,2BAA2B,EAAE,yBAAyB,CAAC,CAAA;IAC7E,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;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAsF;IAC5K,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,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA;QACjC,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,uBAAuB,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;QAC7C,OAAO,kBAAkB,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verified-fetch.d.ts","sourceRoot":"","sources":["../../src/verified-fetch.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,IAAI,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"verified-fetch.d.ts","sourceRoot":"","sources":["../../src/verified-fetch.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,IAAI,EAAE,MAAM,aAAa,CAAA;AAiC1D,OAAO,KAAK,EAAgC,0BAA0B,EAAE,QAAQ,EAAE,iBAAiB,IAAI,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAE/I,OAAO,KAAK,EAAE,KAAK,EAAqB,MAAM,kBAAkB,CAAA;AAQhE,UAAU,uBAAuB;IAC/B,KAAK,EAAE,KAAK,CAAA;IACZ,IAAI,CAAC,EAAE,IAAI,CAAA;CACZ;AA4DD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAO;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA+B;IACjE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqC;gBAE3D,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,uBAAuB,EAAE,IAAI,CAAC,EAAE,0BAA0B;IAexF,OAAO,CAAC,aAAa;IAgBrB;;;OAGG;YACW,gBAAgB;IAgC9B;;;OAGG;YACW,SAAS;IAWvB;;;OAGG;YACW,SAAS;YAcT,UAAU;YA2BV,aAAa;YAgEb,WAAW;YAoGX,SAAS;YA2BT,cAAc;IA0B5B;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAO7B;IAED;;;;;;OAMG;IACG,KAAK,CAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAoHhF;;OAEG;IACG,KAAK,IAAK,OAAO,CAAC,IAAI,CAAC;IAI7B;;OAEG;IACG,IAAI,IAAK,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -24,12 +24,14 @@ import { getETag } from './utils/get-e-tag.js';
|
|
|
24
24
|
import { getResolvedAcceptHeader } from './utils/get-resolved-accept-header.js';
|
|
25
25
|
import { getStreamFromAsyncIterable } from './utils/get-stream-from-async-iterable.js';
|
|
26
26
|
import { tarStream } from './utils/get-tar-stream.js';
|
|
27
|
+
import { getRedirectResponse } from './utils/handle-redirects.js';
|
|
27
28
|
import { parseResource } from './utils/parse-resource.js';
|
|
29
|
+
import {} from './utils/parse-url-string.js';
|
|
28
30
|
import { resourceToSessionCacheKey } from './utils/resource-to-cache-key.js';
|
|
29
|
-
import { setCacheControlHeader } from './utils/response-headers.js';
|
|
31
|
+
import { setCacheControlHeader, setIpfsRoots } from './utils/response-headers.js';
|
|
30
32
|
import { badRequestResponse, movedPermanentlyResponse, notAcceptableResponse, notSupportedResponse, okResponse, badRangeResponse, okRangeResponse, badGatewayResponse, notFoundResponse } from './utils/responses.js';
|
|
31
33
|
import { selectOutputType } from './utils/select-output-type.js';
|
|
32
|
-
import {
|
|
34
|
+
import { handlePathWalking, isObjectNode } from './utils/walk-path.js';
|
|
33
35
|
const SESSION_CACHE_MAX_SIZE = 100;
|
|
34
36
|
const SESSION_CACHE_TTL_MS = 60 * 1000;
|
|
35
37
|
function convertOptions(options) {
|
|
@@ -99,7 +101,8 @@ export class VerifiedFetch {
|
|
|
99
101
|
});
|
|
100
102
|
this.log.trace('created VerifiedFetch instance');
|
|
101
103
|
}
|
|
102
|
-
getBlockstore(root,
|
|
104
|
+
getBlockstore(root, resource, useSession, options) {
|
|
105
|
+
const key = resourceToSessionCacheKey(resource);
|
|
103
106
|
if (!useSession) {
|
|
104
107
|
return this.helia.blockstore;
|
|
105
108
|
}
|
|
@@ -144,8 +147,8 @@ export class VerifiedFetch {
|
|
|
144
147
|
* Accepts a `CID` and returns a `Response` with a body stream that is a CAR
|
|
145
148
|
* of the `DAG` referenced by the `CID`.
|
|
146
149
|
*/
|
|
147
|
-
async handleCar({ resource, cid, session,
|
|
148
|
-
const blockstore = this.getBlockstore(cid,
|
|
150
|
+
async handleCar({ resource, cid, session, options }) {
|
|
151
|
+
const blockstore = this.getBlockstore(cid, resource, session, options);
|
|
149
152
|
const c = car({ blockstore, dagWalkers: this.helia.dagWalkers });
|
|
150
153
|
const stream = toBrowserReadableStream(c.stream(cid, options));
|
|
151
154
|
const response = okResponse(resource, stream);
|
|
@@ -156,19 +159,19 @@ export class VerifiedFetch {
|
|
|
156
159
|
* Accepts a UnixFS `CID` and returns a `.tar` file containing the file or
|
|
157
160
|
* directory structure referenced by the `CID`.
|
|
158
161
|
*/
|
|
159
|
-
async handleTar({ resource, cid, path, session,
|
|
162
|
+
async handleTar({ resource, cid, path, session, options }) {
|
|
160
163
|
if (cid.code !== dagPbCode && cid.code !== rawCode) {
|
|
161
164
|
return notAcceptableResponse('only UnixFS data can be returned in a TAR file');
|
|
162
165
|
}
|
|
163
|
-
const blockstore = this.getBlockstore(cid,
|
|
166
|
+
const blockstore = this.getBlockstore(cid, resource, session, options);
|
|
164
167
|
const stream = toBrowserReadableStream(tarStream(`/ipfs/${cid}/${path}`, blockstore, options));
|
|
165
168
|
const response = okResponse(resource, stream);
|
|
166
169
|
response.headers.set('content-type', 'application/x-tar');
|
|
167
170
|
return response;
|
|
168
171
|
}
|
|
169
|
-
async handleJson({ resource, cid, path, accept, session,
|
|
172
|
+
async handleJson({ resource, cid, path, accept, session, options }) {
|
|
170
173
|
this.log.trace('fetching %c/%s', cid, path);
|
|
171
|
-
const blockstore = this.getBlockstore(cid,
|
|
174
|
+
const blockstore = this.getBlockstore(cid, resource, session, options);
|
|
172
175
|
const block = await blockstore.get(cid, options);
|
|
173
176
|
let body;
|
|
174
177
|
if (accept === 'application/vnd.ipld.dag-cbor' || accept === 'application/cbor') {
|
|
@@ -192,32 +195,25 @@ export class VerifiedFetch {
|
|
|
192
195
|
response.headers.set('content-type', accept ?? 'application/json');
|
|
193
196
|
return response;
|
|
194
197
|
}
|
|
195
|
-
async handleDagCbor({ resource, cid, path, accept, session,
|
|
198
|
+
async handleDagCbor({ resource, cid, path, accept, session, options }) {
|
|
196
199
|
this.log.trace('fetching %c/%s', cid, path);
|
|
197
200
|
let terminalElement;
|
|
198
|
-
|
|
199
|
-
const blockstore = this.getBlockstore(cid, cacheKey, session, options);
|
|
201
|
+
const blockstore = this.getBlockstore(cid, resource, session, options);
|
|
200
202
|
// need to walk path, if it exists, to get the terminal element
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const potentialTerminalElement = pathDetails.terminalElement;
|
|
205
|
-
if (potentialTerminalElement == null) {
|
|
206
|
-
return notFoundResponse(resource);
|
|
207
|
-
}
|
|
208
|
-
if (isObjectNode(potentialTerminalElement)) {
|
|
209
|
-
terminalElement = potentialTerminalElement;
|
|
210
|
-
}
|
|
203
|
+
const pathDetails = await handlePathWalking({ cid, path, resource, options, blockstore, log: this.log });
|
|
204
|
+
if (pathDetails instanceof Response) {
|
|
205
|
+
return pathDetails;
|
|
211
206
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
this
|
|
218
|
-
|
|
207
|
+
const ipfsRoots = pathDetails.ipfsRoots;
|
|
208
|
+
if (isObjectNode(pathDetails.terminalElement)) {
|
|
209
|
+
terminalElement = pathDetails.terminalElement;
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
// this should never happen, but if it does, we should log it and return notSupportedResponse
|
|
213
|
+
this.log.error('terminal element is not a dag-cbor node');
|
|
214
|
+
return notSupportedResponse(resource, 'Terminal element is not a dag-cbor node');
|
|
219
215
|
}
|
|
220
|
-
const block = terminalElement
|
|
216
|
+
const block = terminalElement.node;
|
|
221
217
|
let body;
|
|
222
218
|
if (accept === 'application/octet-stream' || accept === 'application/vnd.ipld.dag-cbor' || accept === 'application/cbor') {
|
|
223
219
|
// skip decoding
|
|
@@ -254,31 +250,20 @@ export class VerifiedFetch {
|
|
|
254
250
|
accept = body instanceof Uint8Array ? 'application/octet-stream' : 'application/json';
|
|
255
251
|
}
|
|
256
252
|
response.headers.set('content-type', accept);
|
|
257
|
-
|
|
258
|
-
response.headers.set('X-Ipfs-Roots', ipfsRoots.map(cid => cid.toV1().toString()).join(',')); // https://specs.ipfs.tech/http-gateways/path-gateway/#x-ipfs-roots-response-header
|
|
259
|
-
}
|
|
253
|
+
setIpfsRoots(response, ipfsRoots);
|
|
260
254
|
return response;
|
|
261
255
|
}
|
|
262
|
-
async handleDagPb({ cid, path, resource,
|
|
263
|
-
let terminalElement;
|
|
264
|
-
let ipfsRoots;
|
|
256
|
+
async handleDagPb({ cid, path, resource, session, options }) {
|
|
265
257
|
let redirected = false;
|
|
266
258
|
const byteRangeContext = new ByteRangeContext(this.helia.logger, options?.headers);
|
|
267
|
-
const blockstore = this.getBlockstore(cid,
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
if (['ERR_NO_PROP', 'ERR_NO_TERMINAL_ELEMENT', 'ERR_NOT_FOUND'].includes(err.code)) {
|
|
276
|
-
return notFoundResponse(resource.toString());
|
|
277
|
-
}
|
|
278
|
-
this.log.error('error walking path %s', path, err);
|
|
279
|
-
return badGatewayResponse(resource.toString(), 'Error walking path');
|
|
280
|
-
}
|
|
281
|
-
let resolvedCID = terminalElement?.cid ?? cid;
|
|
259
|
+
const blockstore = this.getBlockstore(cid, resource, session, options);
|
|
260
|
+
const pathDetails = await handlePathWalking({ cid, path, resource, options, blockstore, log: this.log });
|
|
261
|
+
if (pathDetails instanceof Response) {
|
|
262
|
+
return pathDetails;
|
|
263
|
+
}
|
|
264
|
+
const ipfsRoots = pathDetails.ipfsRoots;
|
|
265
|
+
const terminalElement = pathDetails.terminalElement;
|
|
266
|
+
let resolvedCID = terminalElement.cid;
|
|
282
267
|
if (terminalElement?.type === 'directory') {
|
|
283
268
|
const dirCid = terminalElement.cid;
|
|
284
269
|
const redirectCheckNeeded = path === '' ? !resource.toString().endsWith('/') : !path.endsWith('/');
|
|
@@ -346,9 +331,7 @@ export class VerifiedFetch {
|
|
|
346
331
|
redirected
|
|
347
332
|
});
|
|
348
333
|
await this.setContentType(firstChunk, path, response);
|
|
349
|
-
|
|
350
|
-
response.headers.set('X-Ipfs-Roots', ipfsRoots.map(cid => cid.toV1().toString()).join(',')); // https://specs.ipfs.tech/http-gateways/path-gateway/#x-ipfs-roots-response-header
|
|
351
|
-
}
|
|
334
|
+
setIpfsRoots(response, ipfsRoots);
|
|
352
335
|
return response;
|
|
353
336
|
}
|
|
354
337
|
catch (err) {
|
|
@@ -360,9 +343,18 @@ export class VerifiedFetch {
|
|
|
360
343
|
return badGatewayResponse(resource.toString(), 'Unable to stream content');
|
|
361
344
|
}
|
|
362
345
|
}
|
|
363
|
-
async handleRaw({ resource, cid, path, session,
|
|
346
|
+
async handleRaw({ resource, cid, path, session, options, accept }) {
|
|
347
|
+
/**
|
|
348
|
+
* if we have a path, we can't walk it, so we need to return a 404.
|
|
349
|
+
*
|
|
350
|
+
* @see https://github.com/ipfs/gateway-conformance/blob/26994cfb056b717a23bf694ce4e94386728748dd/tests/subdomain_gateway_ipfs_test.go#L198-L204
|
|
351
|
+
*/
|
|
352
|
+
if (path !== '') {
|
|
353
|
+
this.log.trace('404-ing raw codec request for %c/%s', cid, path);
|
|
354
|
+
return notFoundResponse(resource, 'Raw codec does not support paths');
|
|
355
|
+
}
|
|
364
356
|
const byteRangeContext = new ByteRangeContext(this.helia.logger, options?.headers);
|
|
365
|
-
const blockstore = this.getBlockstore(cid,
|
|
357
|
+
const blockstore = this.getBlockstore(cid, resource, session, options);
|
|
366
358
|
const result = await blockstore.get(cid, options);
|
|
367
359
|
byteRangeContext.setBody(result);
|
|
368
360
|
const response = okRangeResponse(resource, byteRangeContext.getBody(), { byteRangeContext, log: this.log }, {
|
|
@@ -451,8 +443,11 @@ export class VerifiedFetch {
|
|
|
451
443
|
}
|
|
452
444
|
let response;
|
|
453
445
|
let reqFormat;
|
|
454
|
-
const
|
|
455
|
-
|
|
446
|
+
const redirectResponse = await getRedirectResponse({ resource, options, logger: this.helia.logger, cid });
|
|
447
|
+
if (redirectResponse != null) {
|
|
448
|
+
return redirectResponse;
|
|
449
|
+
}
|
|
450
|
+
const handlerArgs = { resource: resource.toString(), cid, path, accept, session: options?.session ?? true, options };
|
|
456
451
|
if (accept === 'application/vnd.ipfs.ipns-record') {
|
|
457
452
|
// the user requested a raw IPNS record
|
|
458
453
|
reqFormat = 'ipns-record';
|