@helia/trustless-gateway-client 0.0.0-9114743f
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 +71 -0
- package/dist/index.min.js +33 -0
- package/dist/index.min.js.map +7 -0
- package/dist/src/broker.d.ts +44 -0
- package/dist/src/broker.d.ts.map +1 -0
- package/dist/src/broker.js +75 -0
- package/dist/src/broker.js.map +1 -0
- package/dist/src/index.d.ts +64 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +19 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/session.d.ts +30 -0
- package/dist/src/session.d.ts.map +1 -0
- package/dist/src/session.js +89 -0
- package/dist/src/session.js.map +1 -0
- package/dist/src/trustless-gateway.d.ts +64 -0
- package/dist/src/trustless-gateway.d.ts.map +1 -0
- package/dist/src/trustless-gateway.js +217 -0
- package/dist/src/trustless-gateway.js.map +1 -0
- package/dist/src/utils.d.ts +27 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +106 -0
- package/dist/src/utils.js.map +1 -0
- package/package.json +78 -0
- package/src/broker.ts +112 -0
- package/src/index.ts +81 -0
- package/src/session.ts +119 -0
- package/src/trustless-gateway.ts +279 -0
- package/src/utils.ts +141 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trustless-gateway.js","sourceRoot":"","sources":["../../src/trustless-gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { TrustlessGateway } from './trustless-gateway.ts';
|
|
2
|
+
import type { TrustlessGatewayGetBlockProgressEvents } from './index.ts';
|
|
3
|
+
import type { TransformRequestInit } from './trustless-gateway.ts';
|
|
4
|
+
import type { Routing } from '@helia/interface';
|
|
5
|
+
import type { Multiaddr } from '@multiformats/multiaddr';
|
|
6
|
+
import type { AbortOptions } from 'abort-error';
|
|
7
|
+
import type { ComponentLogger, Logger } from 'birnam';
|
|
8
|
+
import type { CID } from 'multiformats/cid';
|
|
9
|
+
import type { ProgressOptions } from 'progress-events';
|
|
10
|
+
export declare function filterNonHTTPMultiaddrs(multiaddrs: Multiaddr[], allowInsecure: boolean, allowLocal: boolean): Multiaddr[];
|
|
11
|
+
export interface FindHttpGatewayProvidersOptions extends AbortOptions, ProgressOptions<TrustlessGatewayGetBlockProgressEvents> {
|
|
12
|
+
transformRequestInit?: TransformRequestInit;
|
|
13
|
+
}
|
|
14
|
+
export declare function findHttpGatewayProviders(cid: CID, routing: Routing, logger: ComponentLogger, allowInsecure: boolean, allowLocal: boolean, options?: FindHttpGatewayProvidersOptions): AsyncGenerator<TrustlessGateway>;
|
|
15
|
+
interface LimitedResponseOptions {
|
|
16
|
+
signal?: AbortSignal;
|
|
17
|
+
log?: Logger;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A function that handles ensuring the content-length header and the response body is less than a given byte limit.
|
|
21
|
+
*
|
|
22
|
+
* If the response contains a content-length header greater than the limit or the actual bytes returned are greater than
|
|
23
|
+
* the limit, an error is thrown.
|
|
24
|
+
*/
|
|
25
|
+
export declare function limitedResponse(response: Response, byteLimit: number, options?: LimitedResponseOptions): Promise<Uint8Array>;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,KAAK,EAAE,sCAAsC,EAAE,MAAM,YAAY,CAAA;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACrD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,wBAAgB,uBAAuB,CAAE,UAAU,EAAE,SAAS,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,GAAG,SAAS,EAAE,CAiC1H;AAED,MAAM,WAAW,+BAAgC,SAAQ,YAAY,EAAE,eAAe,CAAC,sCAAsC,CAAC;IAC5H,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;CAC5C;AAED,wBAAwB,wBAAwB,CAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAE,+BAAoC,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAqBnO;AAED,UAAU,sBAAsB;IAC9B,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,CAqDnI"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { getNetConfig, isPrivate } from '@libp2p/utils';
|
|
2
|
+
import { DNS, HTTP, HTTPS } from '@multiformats/multiaddr-matcher';
|
|
3
|
+
import { multiaddrToUri } from '@multiformats/multiaddr-to-uri';
|
|
4
|
+
import { Uint8ArrayList } from 'uint8arraylist';
|
|
5
|
+
import { TrustlessGateway } from "./trustless-gateway.js";
|
|
6
|
+
export function filterNonHTTPMultiaddrs(multiaddrs, allowInsecure, allowLocal) {
|
|
7
|
+
return multiaddrs.filter(ma => {
|
|
8
|
+
const isHttps = HTTPS.exactMatch(ma);
|
|
9
|
+
const isHttp = HTTP.exactMatch(ma);
|
|
10
|
+
if (!isHttps && !isHttp) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
if (isHttps || (allowInsecure && isHttp)) {
|
|
14
|
+
if (allowLocal) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
if (DNS.matches(ma)) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return isPrivate(ma) === false;
|
|
21
|
+
}
|
|
22
|
+
// When allowInsecure is false and allowLocal is true, allow multiaddrs with
|
|
23
|
+
// "127.0.0.1", "localhost", or any subdomain ending with ".localhost"
|
|
24
|
+
if (!allowInsecure && allowLocal) {
|
|
25
|
+
const { host } = getNetConfig(ma);
|
|
26
|
+
if (host === '127.0.0.1' || host === 'localhost' || host.endsWith('.localhost')) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export async function* findHttpGatewayProviders(cid, routing, logger, allowInsecure, allowLocal, options = {}) {
|
|
34
|
+
for await (const provider of routing.findProviders(cid, options)) {
|
|
35
|
+
// require http(s) addresses
|
|
36
|
+
const httpAddresses = filterNonHTTPMultiaddrs(provider.multiaddrs, allowInsecure, allowLocal);
|
|
37
|
+
if (httpAddresses.length === 0) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
// take first address?
|
|
41
|
+
// /ip4/x.x.x.x/tcp/31337/http
|
|
42
|
+
// /ip4/x.x.x.x/tcp/31337/https
|
|
43
|
+
// etc
|
|
44
|
+
const uri = new URL(multiaddrToUri(httpAddresses[0]));
|
|
45
|
+
yield new TrustlessGateway(uri, {
|
|
46
|
+
logger,
|
|
47
|
+
transformRequestInit: options.transformRequestInit,
|
|
48
|
+
routing: provider.routing
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A function that handles ensuring the content-length header and the response body is less than a given byte limit.
|
|
54
|
+
*
|
|
55
|
+
* If the response contains a content-length header greater than the limit or the actual bytes returned are greater than
|
|
56
|
+
* the limit, an error is thrown.
|
|
57
|
+
*/
|
|
58
|
+
export async function limitedResponse(response, byteLimit, options) {
|
|
59
|
+
const { signal, log } = options ?? {};
|
|
60
|
+
const contentLength = response.headers.get('content-length');
|
|
61
|
+
if (contentLength != null) {
|
|
62
|
+
const contentLengthNumber = parseInt(contentLength, 10);
|
|
63
|
+
if (contentLengthNumber > byteLimit) {
|
|
64
|
+
log?.error('content-length header (%d) is greater than the limit (%d)', contentLengthNumber, byteLimit);
|
|
65
|
+
if (response.body != null) {
|
|
66
|
+
await response.body.cancel().catch(err => {
|
|
67
|
+
log?.error('error cancelling response body after content-length check - %e', err);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
throw new Error(`Content-Length header (${contentLengthNumber}) is greater than the limit (${byteLimit}).`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const reader = response.body?.getReader();
|
|
74
|
+
if (reader == null) {
|
|
75
|
+
// no body to consume if reader is null
|
|
76
|
+
throw new Error('Response body is not readable');
|
|
77
|
+
}
|
|
78
|
+
const chunkList = new Uint8ArrayList();
|
|
79
|
+
try {
|
|
80
|
+
while (true) {
|
|
81
|
+
if (signal?.aborted === true) {
|
|
82
|
+
throw new Error('Response body read was aborted.');
|
|
83
|
+
}
|
|
84
|
+
const { done, value } = await reader.read();
|
|
85
|
+
if (done) {
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
chunkList.append(value);
|
|
89
|
+
if (chunkList.byteLength > byteLimit) {
|
|
90
|
+
// No need to consume body here, as we were streaming and hit the limit
|
|
91
|
+
throw new Error(`Response body is greater than the limit (${byteLimit}), received ${chunkList.byteLength} bytes.`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
reader.cancel()
|
|
97
|
+
.catch(err => {
|
|
98
|
+
log?.error('error cancelling reader - %e', err);
|
|
99
|
+
})
|
|
100
|
+
.finally(() => {
|
|
101
|
+
reader.releaseLock();
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return chunkList.subarray();
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@helia/trustless-gateway-client",
|
|
3
|
+
"version": "0.0.0-9114743f",
|
|
4
|
+
"description": "Use Trustless HTTP Gateways with Helia",
|
|
5
|
+
"license": "Apache-2.0 OR MIT",
|
|
6
|
+
"homepage": "https://github.com/ipfs/helia/tree/main/packages/trustless-gateway-client#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ipfs/helia.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/ipfs/helia/issues"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public",
|
|
16
|
+
"provenance": true
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"IPFS"
|
|
20
|
+
],
|
|
21
|
+
"type": "module",
|
|
22
|
+
"types": "./dist/src/index.d.ts",
|
|
23
|
+
"files": [
|
|
24
|
+
"src",
|
|
25
|
+
"dist",
|
|
26
|
+
"!dist/test",
|
|
27
|
+
"!**/*.tsbuildinfo"
|
|
28
|
+
],
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/src/index.d.ts",
|
|
32
|
+
"import": "./dist/src/index.js",
|
|
33
|
+
"module-sync": "./dist/src/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"clean": "aegir clean",
|
|
38
|
+
"lint": "aegir lint",
|
|
39
|
+
"dep-check": "aegir dep-check",
|
|
40
|
+
"doc-check": "aegir doc-check",
|
|
41
|
+
"build": "aegir build",
|
|
42
|
+
"test": "aegir test",
|
|
43
|
+
"test:chrome": "aegir test -t browser --cov",
|
|
44
|
+
"test:chrome-webworker": "aegir test -t webworker",
|
|
45
|
+
"test:firefox": "aegir test -t browser -- --browser firefox",
|
|
46
|
+
"test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
|
|
47
|
+
"test:node": "aegir test -t node --cov",
|
|
48
|
+
"test:electron-main": "aegir test -t electron-main"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@helia/interface": "6.2.1-9114743f",
|
|
52
|
+
"@helia/utils": "2.5.2-9114743f",
|
|
53
|
+
"@libp2p/utils": "^7.2.2",
|
|
54
|
+
"@multiformats/multiaddr": "^13.0.3",
|
|
55
|
+
"@multiformats/multiaddr-matcher": "^3.0.2",
|
|
56
|
+
"@multiformats/multiaddr-to-uri": "^12.0.0",
|
|
57
|
+
"@multiformats/uri-to-multiaddr": "^10.0.0",
|
|
58
|
+
"abort-error": "^1.0.2",
|
|
59
|
+
"birnam": "^1.0.0",
|
|
60
|
+
"multiformats": "^14.0.0",
|
|
61
|
+
"progress-events": "^1.1.0",
|
|
62
|
+
"uint8arraylist": "^3.0.2",
|
|
63
|
+
"uint8arrays": "^6.1.1"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@ipshipyard/crypto": "^1.1.0",
|
|
67
|
+
"aegir": "^48.0.11",
|
|
68
|
+
"cors": "^2.8.6",
|
|
69
|
+
"polka": "^0.5.2",
|
|
70
|
+
"race-signal": "^2.0.0",
|
|
71
|
+
"sinon": "^22.0.0",
|
|
72
|
+
"sinon-ts": "^2.0.0"
|
|
73
|
+
},
|
|
74
|
+
"browser": {
|
|
75
|
+
"./dist/src/utils/delegated-http-routing-defaults.js": "./dist/src/utils/delegated-http-routing-defaults.browser.js"
|
|
76
|
+
},
|
|
77
|
+
"sideEffects": false
|
|
78
|
+
}
|
package/src/broker.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { DEFAULT_ALLOW_INSECURE, DEFAULT_ALLOW_LOCAL } from './index.ts'
|
|
2
|
+
import { createTrustlessGatewaySession } from './session.ts'
|
|
3
|
+
import { findHttpGatewayProviders } from './utils.ts'
|
|
4
|
+
import type { TrustlessGatewayBlockBrokerInit, TrustlessGatewayBlockBrokerComponents, TrustlessGatewayGetBlockProgressEvents } from './index.ts'
|
|
5
|
+
import type { TransformRequestInit } from './trustless-gateway.ts'
|
|
6
|
+
import type { Routing, BlockRetrievalOptions, BlockBroker, CreateSessionOptions, SessionBlockBroker } from '@helia/interface'
|
|
7
|
+
import type { ComponentLogger, Logger } from 'birnam'
|
|
8
|
+
import type { CID } from 'multiformats/cid'
|
|
9
|
+
|
|
10
|
+
export interface CreateTrustlessGatewaySessionOptions extends CreateSessionOptions<TrustlessGatewayGetBlockProgressEvents> {
|
|
11
|
+
/**
|
|
12
|
+
* By default we will only connect to peers with HTTPS addresses, pass true
|
|
13
|
+
* to also connect to HTTP addresses.
|
|
14
|
+
*
|
|
15
|
+
* @default false
|
|
16
|
+
*/
|
|
17
|
+
allowInsecure?: boolean
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* By default we will only connect to peers with public or DNS addresses, pass
|
|
21
|
+
* true to also connect to private addresses.
|
|
22
|
+
*
|
|
23
|
+
* @default false
|
|
24
|
+
*/
|
|
25
|
+
allowLocal?: boolean
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Provide a function that will be called before querying trustless-gateways.
|
|
29
|
+
*
|
|
30
|
+
* This lets you modify the fetch options to pass custom headers or other
|
|
31
|
+
* necessary things.
|
|
32
|
+
*/
|
|
33
|
+
transformRequestInit?: TransformRequestInit
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A class that accepts a list of trustless gateways that are queried
|
|
38
|
+
* for blocks.
|
|
39
|
+
*/
|
|
40
|
+
export class TrustlessGatewayBlockBroker implements BlockBroker<TrustlessGatewayGetBlockProgressEvents> {
|
|
41
|
+
public readonly name = 'trustless-gateway'
|
|
42
|
+
private readonly allowInsecure: boolean
|
|
43
|
+
private readonly allowLocal: boolean
|
|
44
|
+
private readonly transformRequestInit?: TransformRequestInit
|
|
45
|
+
private readonly routing: Routing
|
|
46
|
+
private readonly log: Logger
|
|
47
|
+
private readonly logger: ComponentLogger
|
|
48
|
+
|
|
49
|
+
constructor (components: TrustlessGatewayBlockBrokerComponents, init: TrustlessGatewayBlockBrokerInit = {}) {
|
|
50
|
+
this.log = components.logger.forComponent('helia:trustless-gateway-block-broker')
|
|
51
|
+
this.logger = components.logger
|
|
52
|
+
this.routing = components.routing
|
|
53
|
+
this.allowInsecure = init.allowInsecure ?? DEFAULT_ALLOW_INSECURE
|
|
54
|
+
this.allowLocal = init.allowLocal ?? DEFAULT_ALLOW_LOCAL
|
|
55
|
+
this.transformRequestInit = init.transformRequestInit
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async retrieve (cid: CID, options: BlockRetrievalOptions<TrustlessGatewayGetBlockProgressEvents> = {}): Promise<Uint8Array> {
|
|
59
|
+
const aggregateErrors: Error[] = []
|
|
60
|
+
|
|
61
|
+
for await (const gateway of findHttpGatewayProviders(cid, this.routing, this.logger, this.allowInsecure, this.allowLocal, { ...options, transformRequestInit: this.transformRequestInit })) {
|
|
62
|
+
this.log('getting block for %c from %s', cid, gateway.url)
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
const block = await gateway.getRawBlock(cid, options)
|
|
66
|
+
this.log.trace('got block for %c from %s', cid, gateway.url)
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
await options.validateFn?.(block)
|
|
70
|
+
} catch (err) {
|
|
71
|
+
this.log.error('failed to validate block for %c from %s - %e', cid, gateway.url, err)
|
|
72
|
+
// try another gateway
|
|
73
|
+
continue
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return block
|
|
77
|
+
} catch (err: unknown) {
|
|
78
|
+
this.log.error('failed to get block for %c from %s - %e', cid, gateway.url, err)
|
|
79
|
+
|
|
80
|
+
if (err instanceof Error) {
|
|
81
|
+
aggregateErrors.push(err)
|
|
82
|
+
} else {
|
|
83
|
+
aggregateErrors.push(new Error(`Unable to fetch raw block for CID ${cid} from gateway ${gateway.url}`))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// if signal was aborted, exit the loop
|
|
87
|
+
if (options.signal?.aborted === true) {
|
|
88
|
+
this.log.trace('request aborted while fetching raw block for CID %c from gateway %s', cid, gateway.url)
|
|
89
|
+
break
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (aggregateErrors.length > 0) {
|
|
95
|
+
throw new AggregateError(aggregateErrors, `Unable to fetch raw block for CID ${cid} from any gateway`)
|
|
96
|
+
} else {
|
|
97
|
+
throw new Error(`Unable to fetch raw block for CID ${cid} from any gateway`)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
createSession (options: CreateTrustlessGatewaySessionOptions = {}): SessionBlockBroker<TrustlessGatewayGetBlockProgressEvents> {
|
|
102
|
+
return createTrustlessGatewaySession({
|
|
103
|
+
logger: this.logger,
|
|
104
|
+
routing: this.routing
|
|
105
|
+
}, {
|
|
106
|
+
...options,
|
|
107
|
+
allowLocal: this.allowLocal,
|
|
108
|
+
allowInsecure: this.allowInsecure,
|
|
109
|
+
transformRequestInit: this.transformRequestInit
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* A Trustless Gateway is an HTTP endpoint that can be used to download blocks
|
|
5
|
+
* or CAR files in a verifiable way.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { TrustlessGatewayBlockBroker } from './broker.ts'
|
|
9
|
+
import type { TransformRequestInit } from './trustless-gateway.ts'
|
|
10
|
+
import type { Routing, BlockBroker, RoutingFindProvidersProgressEvents, BlockBrokerGetBlockProgressEvents } from '@helia/interface'
|
|
11
|
+
import type { ComponentLogger } from 'birnam'
|
|
12
|
+
import type { CID } from 'multiformats'
|
|
13
|
+
import type { ProgressEvent } from 'progress-events'
|
|
14
|
+
|
|
15
|
+
export const DEFAULT_ALLOW_INSECURE = false
|
|
16
|
+
export const DEFAULT_ALLOW_LOCAL = false
|
|
17
|
+
/**
|
|
18
|
+
* The maximum number of bytes to allow when fetching a raw block.
|
|
19
|
+
*
|
|
20
|
+
* @see https://specs.ipfs.tech/bitswap-protocol/#block-sizes
|
|
21
|
+
*/
|
|
22
|
+
export const DEFAULT_MAX_SIZE = 2_097_152
|
|
23
|
+
|
|
24
|
+
export interface TrustlessGatewayProvider {
|
|
25
|
+
/**
|
|
26
|
+
* The type of provider
|
|
27
|
+
*/
|
|
28
|
+
type: 'trustless-gateway'
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The CID that the provider can provide the block for
|
|
32
|
+
*/
|
|
33
|
+
cid: CID
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The provider's URL
|
|
37
|
+
*/
|
|
38
|
+
url: string
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Which routing implementation found the provider
|
|
42
|
+
*/
|
|
43
|
+
routing: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type TrustlessGatewayGetBlockProgressEvents =
|
|
47
|
+
ProgressEvent<'trustless-gateway:get-block:fetch', URL> |
|
|
48
|
+
ProgressEvent<'trustless-gateway:found-provider', TrustlessGatewayProvider> |
|
|
49
|
+
RoutingFindProvidersProgressEvents |
|
|
50
|
+
BlockBrokerGetBlockProgressEvents
|
|
51
|
+
|
|
52
|
+
export interface TrustlessGatewayBlockBrokerInit {
|
|
53
|
+
/**
|
|
54
|
+
* By default we will only connect to peers with HTTPS addresses, pass true
|
|
55
|
+
* to also connect to HTTP addresses.
|
|
56
|
+
*
|
|
57
|
+
* @default false
|
|
58
|
+
*/
|
|
59
|
+
allowInsecure?: boolean
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* By default we will only connect to peers with public or DNS addresses, pass
|
|
63
|
+
* true to also connect to private addresses.
|
|
64
|
+
*
|
|
65
|
+
* @default false
|
|
66
|
+
*/
|
|
67
|
+
allowLocal?: boolean
|
|
68
|
+
/**
|
|
69
|
+
* Provide a function that will be called before querying trustless-gateways. This lets you modify the fetch options to pass custom headers or other necessary things.
|
|
70
|
+
*/
|
|
71
|
+
transformRequestInit?: TransformRequestInit
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface TrustlessGatewayBlockBrokerComponents {
|
|
75
|
+
routing: Routing
|
|
76
|
+
logger: ComponentLogger
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function trustlessGatewayBlockBroker (init: TrustlessGatewayBlockBrokerInit = {}): (components: TrustlessGatewayBlockBrokerComponents) => BlockBroker<TrustlessGatewayGetBlockProgressEvents> {
|
|
80
|
+
return (components) => new TrustlessGatewayBlockBroker(components, init)
|
|
81
|
+
}
|
package/src/session.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { AbstractSession, isCID } from '@helia/utils'
|
|
2
|
+
import { multiaddrToUri } from '@multiformats/multiaddr-to-uri'
|
|
3
|
+
import { CID } from 'multiformats/cid'
|
|
4
|
+
import { CustomProgressEvent } from 'progress-events'
|
|
5
|
+
import { DEFAULT_ALLOW_INSECURE, DEFAULT_ALLOW_LOCAL } from './index.ts'
|
|
6
|
+
import { TrustlessGateway } from './trustless-gateway.ts'
|
|
7
|
+
import { filterNonHTTPMultiaddrs, findHttpGatewayProviders } from './utils.ts'
|
|
8
|
+
import type { CreateTrustlessGatewaySessionOptions } from './broker.ts'
|
|
9
|
+
import type { TrustlessGatewayGetBlockProgressEvents, TrustlessGatewayProvider } from './index.ts'
|
|
10
|
+
import type { TransformRequestInit } from './trustless-gateway.ts'
|
|
11
|
+
import type { BlockRetrievalOptions, Routing } from '@helia/interface'
|
|
12
|
+
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
13
|
+
import type { AbortOptions } from 'abort-error'
|
|
14
|
+
import type { ComponentLogger } from 'birnam'
|
|
15
|
+
|
|
16
|
+
export interface TrustlessGatewaySessionComponents {
|
|
17
|
+
logger: ComponentLogger
|
|
18
|
+
routing: Routing
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class TrustlessGatewaySession extends AbstractSession<TrustlessGateway, TrustlessGatewayGetBlockProgressEvents> {
|
|
22
|
+
public readonly name = 'trustless-gateway-session'
|
|
23
|
+
private readonly routing: Routing
|
|
24
|
+
private readonly allowInsecure: boolean
|
|
25
|
+
private readonly allowLocal: boolean
|
|
26
|
+
private readonly transformRequestInit?: TransformRequestInit
|
|
27
|
+
|
|
28
|
+
constructor (components: TrustlessGatewaySessionComponents, init: CreateTrustlessGatewaySessionOptions) {
|
|
29
|
+
super(components, {
|
|
30
|
+
...init,
|
|
31
|
+
name: 'helia:trustless-gateway:session'
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
this.routing = components.routing
|
|
35
|
+
this.allowInsecure = init.allowInsecure ?? DEFAULT_ALLOW_INSECURE
|
|
36
|
+
this.allowLocal = init.allowLocal ?? DEFAULT_ALLOW_LOCAL
|
|
37
|
+
this.transformRequestInit = init.transformRequestInit
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async queryProvider (cid: CID, provider: TrustlessGateway, options: BlockRetrievalOptions): Promise<Uint8Array> {
|
|
41
|
+
this.log('fetching BLOCK for %c from %s', cid, provider.url)
|
|
42
|
+
|
|
43
|
+
options?.onProgress?.(new CustomProgressEvent('helia:block-brokers:query-provider:start', {
|
|
44
|
+
blockBroker: 'trustless-gateway',
|
|
45
|
+
provider: provider.url,
|
|
46
|
+
transport: 'http',
|
|
47
|
+
cid
|
|
48
|
+
}))
|
|
49
|
+
|
|
50
|
+
let block: Uint8Array
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
block = await provider.getRawBlock(cid, options)
|
|
54
|
+
this.log.trace('got block for %c from %s', cid, provider.url)
|
|
55
|
+
} finally {
|
|
56
|
+
options?.onProgress?.(new CustomProgressEvent('helia:block-brokers:query-provider:end', {
|
|
57
|
+
blockBroker: 'trustless-gateway',
|
|
58
|
+
provider: provider.url,
|
|
59
|
+
transport: 'http',
|
|
60
|
+
cid
|
|
61
|
+
}))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
await options.validateFn?.(block)
|
|
65
|
+
|
|
66
|
+
return block
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async * findNewProviders (cid: CID, options: AbortOptions = {}): AsyncGenerator<TrustlessGateway> {
|
|
70
|
+
yield * findHttpGatewayProviders(cid, this.routing, this.logger, this.allowInsecure, this.allowLocal, { ...options, transformRequestInit: this.transformRequestInit })
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
toFilterKey (provider: TrustlessGateway): Uint8Array | string {
|
|
74
|
+
return provider.url.toString()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
equals (providerA: TrustlessGateway, providerB: TrustlessGateway): boolean {
|
|
78
|
+
return providerA.url.toString() === providerB.url.toString()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async convertToProvider (provider: CID | Multiaddr | Multiaddr[], routing: string, options?: AbortOptions): Promise<TrustlessGateway | undefined> {
|
|
82
|
+
options?.signal?.throwIfAborted()
|
|
83
|
+
|
|
84
|
+
if (isCID(provider)) {
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const httpAddresses = filterNonHTTPMultiaddrs(Array.isArray(provider) ? provider : [provider], this.allowInsecure, this.allowLocal)
|
|
89
|
+
|
|
90
|
+
if (httpAddresses.length === 0) {
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// take first address?
|
|
95
|
+
// /ip4/x.x.x.x/tcp/31337/http
|
|
96
|
+
// /ip4/x.x.x.x/tcp/31337/https
|
|
97
|
+
// etc
|
|
98
|
+
const uri = multiaddrToUri(httpAddresses[0])
|
|
99
|
+
|
|
100
|
+
return new TrustlessGateway(uri, {
|
|
101
|
+
logger: this.logger,
|
|
102
|
+
transformRequestInit: this.transformRequestInit,
|
|
103
|
+
routing
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
emitFoundProviderProgressEvent (cid: CID, provider: TrustlessGateway, options: BlockRetrievalOptions<TrustlessGatewayGetBlockProgressEvents>): void {
|
|
108
|
+
options?.onProgress?.(new CustomProgressEvent<TrustlessGatewayProvider>('trustless-gateway:found-provider', {
|
|
109
|
+
type: 'trustless-gateway',
|
|
110
|
+
cid,
|
|
111
|
+
url: provider.url.toJSON(),
|
|
112
|
+
routing: provider.routing
|
|
113
|
+
}))
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function createTrustlessGatewaySession (components: TrustlessGatewaySessionComponents, init: CreateTrustlessGatewaySessionOptions): TrustlessGatewaySession {
|
|
118
|
+
return new TrustlessGatewaySession(components, init)
|
|
119
|
+
}
|