@helia/block-brokers 2.0.3-9c8a2c0 → 2.0.3-9ea934e
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 +6 -1
- package/dist/src/bitswap.js +3 -3
- package/dist/src/bitswap.js.map +1 -1
- package/dist/src/trustless-gateway/broker.d.ts +2 -8
- package/dist/src/trustless-gateway/broker.d.ts.map +1 -1
- package/dist/src/trustless-gateway/broker.js +8 -83
- package/dist/src/trustless-gateway/broker.js.map +1 -1
- package/dist/src/trustless-gateway/session.d.ts +25 -0
- package/dist/src/trustless-gateway/session.d.ts.map +1 -0
- package/dist/src/trustless-gateway/session.js +68 -0
- package/dist/src/trustless-gateway/session.js.map +1 -0
- package/dist/src/trustless-gateway/trustless-gateway.js +1 -1
- package/dist/src/trustless-gateway/trustless-gateway.js.map +1 -1
- package/package.json +6 -5
- package/src/bitswap.ts +3 -3
- package/src/trustless-gateway/broker.ts +9 -109
- package/src/trustless-gateway/session.ts +98 -0
- package/src/trustless-gateway/trustless-gateway.ts +1 -1
package/dist/src/bitswap.js
CHANGED
|
@@ -43,14 +43,14 @@ class BitswapBlockBroker {
|
|
|
43
43
|
async retrieve(cid, options = {}) {
|
|
44
44
|
return this.bitswap.want(cid, options);
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
const session =
|
|
46
|
+
createSession(options) {
|
|
47
|
+
const session = this.bitswap.createSession(options);
|
|
48
48
|
return {
|
|
49
49
|
announce: async (cid, block, options) => {
|
|
50
50
|
await this.bitswap.notify(cid, block, options);
|
|
51
51
|
},
|
|
52
52
|
retrieve: async (cid, options) => {
|
|
53
|
-
return session.
|
|
53
|
+
return session.retrieve(cid, options);
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
56
|
}
|
package/dist/src/bitswap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitswap.js","sourceRoot":"","sources":["../../src/bitswap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAoB9C,MAAM,kBAAkB;IACL,OAAO,CAAS;IACzB,OAAO,CAAS;IAExB,YAAa,UAA6B,EAAE,OAAoB,EAAE;QAChE,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAA;QAE9B,IAAI,CAAC,OAAO,GAAG,aAAa,CAAC,UAAU,EAAE;YACvC,UAAU,EAAE;gBACV,SAAS,EAAE,KAAK,EAAE,WAA4B,EAAoC,EAAE;oBAClF,IAAI,MAAmC,CAAA;oBAEvC,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;wBACpC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;4BAC5C,OAAO,MAAM,CAAC,IAAI,KAAK,WAAW,CAAA;wBACpC,CAAC,CAAC,CAAA;oBACJ,CAAC;yBAAM,CAAC;wBACN,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;oBAC/B,CAAC;oBAED,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;wBACnB,OAAO,MAAM,CAAA;oBACf,CAAC;oBAED,MAAM,IAAI,KAAK,CAAC,wCAAwC,WAAW,GAAG,CAAC,CAAA;gBACzE,CAAC;aACF;YACD,GAAG,IAAI;SACR,CAAC,CAAA;QACF,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IACtB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;QAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;IACrB,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QACzB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IACtB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAE,GAAQ,EAAE,KAAiB,EAAE,OAA2D;QACtG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;IAChD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAE,GAAQ,EAAE,UAAiE,EAAE;QAC3F,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IACxC,CAAC;IAED,
|
|
1
|
+
{"version":3,"file":"bitswap.js","sourceRoot":"","sources":["../../src/bitswap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAoB9C,MAAM,kBAAkB;IACL,OAAO,CAAS;IACzB,OAAO,CAAS;IAExB,YAAa,UAA6B,EAAE,OAAoB,EAAE;QAChE,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAA;QAE9B,IAAI,CAAC,OAAO,GAAG,aAAa,CAAC,UAAU,EAAE;YACvC,UAAU,EAAE;gBACV,SAAS,EAAE,KAAK,EAAE,WAA4B,EAAoC,EAAE;oBAClF,IAAI,MAAmC,CAAA;oBAEvC,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;wBACpC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;4BAC5C,OAAO,MAAM,CAAC,IAAI,KAAK,WAAW,CAAA;wBACpC,CAAC,CAAC,CAAA;oBACJ,CAAC;yBAAM,CAAC;wBACN,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;oBAC/B,CAAC;oBAED,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;wBACnB,OAAO,MAAM,CAAA;oBACf,CAAC;oBAED,MAAM,IAAI,KAAK,CAAC,wCAAwC,WAAW,GAAG,CAAC,CAAA;gBACzE,CAAC;aACF;YACD,GAAG,IAAI;SACR,CAAC,CAAA;QACF,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IACtB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;QAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;IACrB,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QACzB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IACtB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAE,GAAQ,EAAE,KAAiB,EAAE,OAA2D;QACtG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;IAChD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAE,GAAQ,EAAE,UAAiE,EAAE;QAC3F,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IACxC,CAAC;IAED,aAAa,CAAE,OAA8D;QAC3E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;QAEnD,OAAO;YACL,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBACtC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;YAChD,CAAC;YAED,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;gBAC/B,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;YACvC,CAAC;SACF,CAAA;IACH,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAE,OAAoB,EAAE;IAC7C,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;AACjE,CAAC"}
|
|
@@ -2,13 +2,6 @@ import type { TrustlessGatewayBlockBrokerInit, TrustlessGatewayComponents, Trust
|
|
|
2
2
|
import type { BlockRetrievalOptions, BlockBroker, CreateSessionOptions } from '@helia/interface';
|
|
3
3
|
import type { CID } from 'multiformats/cid';
|
|
4
4
|
export interface CreateTrustlessGatewaySessionOptions extends CreateSessionOptions<TrustlessGatewayGetBlockProgressEvents> {
|
|
5
|
-
/**
|
|
6
|
-
* Specify the cache control header to send to the remote. 'only-if-cached'
|
|
7
|
-
* will prevent the gateway from fetching the content if they don't have it.
|
|
8
|
-
*
|
|
9
|
-
* @default only-if-cached
|
|
10
|
-
*/
|
|
11
|
-
cacheControl?: string;
|
|
12
5
|
/**
|
|
13
6
|
* By default we will only connect to peers with HTTPS addresses, pass true
|
|
14
7
|
* to also connect to HTTP addresses.
|
|
@@ -33,9 +26,10 @@ export declare class TrustlessGatewayBlockBroker implements BlockBroker<Trustles
|
|
|
33
26
|
private readonly gateways;
|
|
34
27
|
private readonly routing;
|
|
35
28
|
private readonly log;
|
|
29
|
+
private readonly logger;
|
|
36
30
|
constructor(components: TrustlessGatewayComponents, init?: TrustlessGatewayBlockBrokerInit);
|
|
37
31
|
addGateway(gatewayOrUrl: string): void;
|
|
38
32
|
retrieve(cid: CID, options?: BlockRetrievalOptions<TrustlessGatewayGetBlockProgressEvents>): Promise<Uint8Array>;
|
|
39
|
-
createSession(
|
|
33
|
+
createSession(options?: CreateTrustlessGatewaySessionOptions): BlockBroker<TrustlessGatewayGetBlockProgressEvents>;
|
|
40
34
|
}
|
|
41
35
|
//# sourceMappingURL=broker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broker.d.ts","sourceRoot":"","sources":["../../../src/trustless-gateway/broker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"broker.d.ts","sourceRoot":"","sources":["../../../src/trustless-gateway/broker.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,+BAA+B,EAAE,0BAA0B,EAAE,sCAAsC,EAAE,MAAM,YAAY,CAAA;AACrI,OAAO,KAAK,EAAW,qBAAqB,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAEzG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAE3C,MAAM,WAAW,oCAAqC,SAAQ,oBAAoB,CAAC,sCAAsC,CAAC;IACxH;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED;;;GAGG;AACH,qBAAa,2BAA4B,YAAW,WAAW,CAAC,sCAAsC,CAAC;IACrG,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;gBAE3B,UAAU,EAAE,0BAA0B,EAAE,IAAI,GAAE,+BAAoC;IAW/F,UAAU,CAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAIjC,QAAQ,CAAE,GAAG,EAAE,GAAG,EAAE,OAAO,GAAE,qBAAqB,CAAC,sCAAsC,CAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IA2C3H,aAAa,CAAE,OAAO,GAAE,oCAAyC,GAAG,WAAW,CAAC,sCAAsC,CAAC;CAMxH"}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PeerQueue } from '@libp2p/utils/peer-queue';
|
|
3
|
-
import { isPrivateIp } from '@libp2p/utils/private-ip';
|
|
4
|
-
import { DNS, HTTP, HTTPS } from '@multiformats/multiaddr-matcher';
|
|
5
|
-
import { multiaddrToUri } from '@multiformats/multiaddr-to-uri';
|
|
6
|
-
import pDefer from 'p-defer';
|
|
1
|
+
import { createTrustlessGatewaySession } from './session.js';
|
|
7
2
|
import { TrustlessGateway } from './trustless-gateway.js';
|
|
8
3
|
import { DEFAULT_TRUSTLESS_GATEWAYS } from './index.js';
|
|
9
4
|
/**
|
|
@@ -15,9 +10,11 @@ export class TrustlessGatewayBlockBroker {
|
|
|
15
10
|
gateways;
|
|
16
11
|
routing;
|
|
17
12
|
log;
|
|
13
|
+
logger;
|
|
18
14
|
constructor(components, init = {}) {
|
|
19
15
|
this.components = components;
|
|
20
16
|
this.log = components.logger.forComponent('helia:trustless-gateway-block-broker');
|
|
17
|
+
this.logger = components.logger;
|
|
21
18
|
this.routing = components.routing;
|
|
22
19
|
this.gateways = (init.gateways ?? DEFAULT_TRUSTLESS_GATEWAYS)
|
|
23
20
|
.map((gatewayOrUrl) => {
|
|
@@ -69,83 +66,11 @@ export class TrustlessGatewayBlockBroker {
|
|
|
69
66
|
throw new Error(`Unable to fetch raw block for CID ${cid} from any gateway`);
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const broker = new TrustlessGatewayBlockBroker(this.components, {
|
|
78
|
-
gateways
|
|
79
|
-
});
|
|
80
|
-
this.log('finding transport-ipfs-gateway-http providers for cid %c', root);
|
|
81
|
-
const queue = new PeerQueue({
|
|
82
|
-
concurrency: options.providerQueryConcurrency ?? DEFAULT_SESSION_PROVIDER_QUERY_CONCURRENCY
|
|
83
|
-
});
|
|
84
|
-
Promise.resolve().then(async () => {
|
|
85
|
-
for await (const provider of this.routing.findProviders(root, options)) {
|
|
86
|
-
const httpAddresses = provider.multiaddrs.filter(ma => {
|
|
87
|
-
if (HTTPS.matches(ma) || (options.allowInsecure === true && HTTP.matches(ma))) {
|
|
88
|
-
if (options.allowLocal === true) {
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
if (DNS.matches(ma)) {
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
|
-
return isPrivateIp(ma.toOptions().host) === false;
|
|
95
|
-
}
|
|
96
|
-
return false;
|
|
97
|
-
});
|
|
98
|
-
if (httpAddresses.length === 0) {
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
this.log('found transport-ipfs-gateway-http provider %p for cid %c', provider.id, root);
|
|
102
|
-
void queue.add(async () => {
|
|
103
|
-
for (const ma of httpAddresses) {
|
|
104
|
-
let uri;
|
|
105
|
-
try {
|
|
106
|
-
// /ip4/x.x.x.x/tcp/31337/http
|
|
107
|
-
// /ip4/x.x.x.x/tcp/31337/https
|
|
108
|
-
// etc
|
|
109
|
-
uri = multiaddrToUri(ma);
|
|
110
|
-
const resource = `${uri}/ipfs/${root.toString()}?format=raw`;
|
|
111
|
-
// make sure the peer is available - HEAD support doesn't seem to
|
|
112
|
-
// be very widely implemented so as long as the remote responds
|
|
113
|
-
// we are happy they are valid
|
|
114
|
-
// https://specs.ipfs.tech/http-gateways/trustless-gateway/#head-ipfs-cid-path-params
|
|
115
|
-
// in the future we should be able to request `${uri}/.well-known/libp2p-http
|
|
116
|
-
// and discover an IPFS gateway from $.protocols['/ipfs/gateway'].path
|
|
117
|
-
// in the response
|
|
118
|
-
// https://github.com/libp2p/specs/pull/508/files
|
|
119
|
-
const response = await fetch(resource, {
|
|
120
|
-
method: 'HEAD',
|
|
121
|
-
headers: {
|
|
122
|
-
Accept: 'application/vnd.ipld.raw',
|
|
123
|
-
'Cache-Control': options.cacheControl ?? 'only-if-cached'
|
|
124
|
-
},
|
|
125
|
-
signal: AbortSignal.timeout(options.providerQueryTimeout ?? DEFAULT_SESSION_PROVIDER_QUERY_TIMEOUT)
|
|
126
|
-
});
|
|
127
|
-
this.log('HEAD %s %d', resource, response.status);
|
|
128
|
-
gateways.push(uri);
|
|
129
|
-
broker.addGateway(uri);
|
|
130
|
-
this.log('found %d transport-ipfs-gateway-http providers for cid %c', gateways.length, root);
|
|
131
|
-
if (gateways.length === minProviders) {
|
|
132
|
-
deferred.resolve(broker);
|
|
133
|
-
}
|
|
134
|
-
if (gateways.length === maxProviders) {
|
|
135
|
-
queue.clear();
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
catch (err) {
|
|
139
|
-
this.log.error('could not fetch %c from %a', root, uri ?? ma, err);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
})
|
|
145
|
-
.catch(err => {
|
|
146
|
-
this.log.error('error creating session for %c', root, err);
|
|
147
|
-
});
|
|
148
|
-
return deferred.promise;
|
|
69
|
+
createSession(options = {}) {
|
|
70
|
+
return createTrustlessGatewaySession({
|
|
71
|
+
logger: this.logger,
|
|
72
|
+
routing: this.routing
|
|
73
|
+
}, options);
|
|
149
74
|
}
|
|
150
75
|
}
|
|
151
76
|
//# sourceMappingURL=broker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broker.js","sourceRoot":"","sources":["../../../src/trustless-gateway/broker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,
|
|
1
|
+
{"version":3,"file":"broker.js","sourceRoot":"","sources":["../../../src/trustless-gateway/broker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AbstractSession } from '@helia/utils';
|
|
2
|
+
import { TrustlessGateway } from './trustless-gateway.js';
|
|
3
|
+
import type { CreateTrustlessGatewaySessionOptions } from './broker.js';
|
|
4
|
+
import type { TrustlessGatewayGetBlockProgressEvents } from './index.js';
|
|
5
|
+
import type { BlockRetrievalOptions, Routing } from '@helia/interface';
|
|
6
|
+
import type { ComponentLogger } from '@libp2p/interface';
|
|
7
|
+
import type { AbortOptions } from 'interface-store';
|
|
8
|
+
import type { CID } from 'multiformats/cid';
|
|
9
|
+
export interface TrustlessGatewaySessionComponents {
|
|
10
|
+
logger: ComponentLogger;
|
|
11
|
+
routing: Routing;
|
|
12
|
+
}
|
|
13
|
+
declare class TrustlessGatewaySession extends AbstractSession<TrustlessGateway, TrustlessGatewayGetBlockProgressEvents> {
|
|
14
|
+
private readonly routing;
|
|
15
|
+
private readonly allowInsecure;
|
|
16
|
+
private readonly allowLocal;
|
|
17
|
+
constructor(components: TrustlessGatewaySessionComponents, init: CreateTrustlessGatewaySessionOptions);
|
|
18
|
+
queryProvider(cid: CID, provider: TrustlessGateway, options: BlockRetrievalOptions): Promise<Uint8Array>;
|
|
19
|
+
findNewProviders(cid: CID, options?: AbortOptions): AsyncGenerator<TrustlessGateway>;
|
|
20
|
+
toEvictionKey(provider: TrustlessGateway): Uint8Array | string;
|
|
21
|
+
equals(providerA: TrustlessGateway, providerB: TrustlessGateway): boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function createTrustlessGatewaySession(components: TrustlessGatewaySessionComponents, init: CreateTrustlessGatewaySessionOptions): TrustlessGatewaySession;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/trustless-gateway/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAI9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,aAAa,CAAA;AACvE,OAAO,KAAK,EAAE,sCAAsC,EAAE,MAAM,YAAY,CAAA;AACxE,OAAO,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAK3C,MAAM,WAAW,iCAAiC;IAChD,MAAM,EAAE,eAAe,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,cAAM,uBAAwB,SAAQ,eAAe,CAAC,gBAAgB,EAAE,sCAAsC,CAAC;IAC7G,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAEvB,UAAU,EAAE,iCAAiC,EAAE,IAAI,EAAE,oCAAoC;IAWhG,aAAa,CAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC;IAWvG,gBAAgB,CAAE,GAAG,EAAE,GAAG,EAAE,OAAO,GAAE,YAAiB,GAAG,cAAc,CAAC,gBAAgB,CAAC;IAoBjG,aAAa,CAAE,QAAQ,EAAE,gBAAgB,GAAG,UAAU,GAAG,MAAM;IAI/D,MAAM,CAAE,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,gBAAgB,GAAG,OAAO;CAG3E;AAoBD,wBAAgB,6BAA6B,CAAE,UAAU,EAAE,iCAAiC,EAAE,IAAI,EAAE,oCAAoC,GAAG,uBAAuB,CAEjK"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { AbstractSession } from '@helia/utils';
|
|
2
|
+
import { isPrivateIp } from '@libp2p/utils/private-ip';
|
|
3
|
+
import { DNS, HTTP, HTTPS } from '@multiformats/multiaddr-matcher';
|
|
4
|
+
import { multiaddrToUri } from '@multiformats/multiaddr-to-uri';
|
|
5
|
+
import { TrustlessGateway } from './trustless-gateway.js';
|
|
6
|
+
const DEFAULT_ALLOW_INSECURE = false;
|
|
7
|
+
const DEFAULT_ALLOW_LOCAL = false;
|
|
8
|
+
class TrustlessGatewaySession extends AbstractSession {
|
|
9
|
+
routing;
|
|
10
|
+
allowInsecure;
|
|
11
|
+
allowLocal;
|
|
12
|
+
constructor(components, init) {
|
|
13
|
+
super(components, {
|
|
14
|
+
...init,
|
|
15
|
+
name: 'helia:trustless-gateway:session'
|
|
16
|
+
});
|
|
17
|
+
this.routing = components.routing;
|
|
18
|
+
this.allowInsecure = init.allowInsecure ?? DEFAULT_ALLOW_INSECURE;
|
|
19
|
+
this.allowLocal = init.allowLocal ?? DEFAULT_ALLOW_LOCAL;
|
|
20
|
+
}
|
|
21
|
+
async queryProvider(cid, provider, options) {
|
|
22
|
+
this.log('fetching BLOCK for %c from %s', cid, provider.url);
|
|
23
|
+
const block = await provider.getRawBlock(cid, options.signal);
|
|
24
|
+
this.log.trace('got block for %c from %s', cid, provider.url);
|
|
25
|
+
await options.validateFn?.(block);
|
|
26
|
+
return block;
|
|
27
|
+
}
|
|
28
|
+
async *findNewProviders(cid, options = {}) {
|
|
29
|
+
for await (const provider of this.routing.findProviders(cid, options)) {
|
|
30
|
+
// require http(s) addresses
|
|
31
|
+
const httpAddresses = filterMultiaddrs(provider.multiaddrs, this.allowInsecure, this.allowLocal);
|
|
32
|
+
if (httpAddresses.length === 0) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// take first address?
|
|
36
|
+
// /ip4/x.x.x.x/tcp/31337/http
|
|
37
|
+
// /ip4/x.x.x.x/tcp/31337/https
|
|
38
|
+
// etc
|
|
39
|
+
const uri = multiaddrToUri(httpAddresses[0]);
|
|
40
|
+
this.log('found http-gateway provider %p %s for cid %c', provider.id, uri, cid);
|
|
41
|
+
yield new TrustlessGateway(uri, this.logger);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
toEvictionKey(provider) {
|
|
45
|
+
return provider.url.toString();
|
|
46
|
+
}
|
|
47
|
+
equals(providerA, providerB) {
|
|
48
|
+
return providerA.url.toString() === providerB.url.toString();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function filterMultiaddrs(multiaddrs, allowInsecure, allowLocal) {
|
|
52
|
+
return multiaddrs.filter(ma => {
|
|
53
|
+
if (HTTPS.matches(ma) || (allowInsecure && HTTP.matches(ma))) {
|
|
54
|
+
if (allowLocal) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
if (DNS.matches(ma)) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
return isPrivateIp(ma.toOptions().host) === false;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
export function createTrustlessGatewaySession(components, init) {
|
|
66
|
+
return new TrustlessGatewaySession(components, init);
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/trustless-gateway/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -40,7 +40,7 @@ export class TrustlessGateway {
|
|
|
40
40
|
* https://specs.ipfs.tech/http-gateways/trustless-gateway/
|
|
41
41
|
*/
|
|
42
42
|
async getRawBlock(cid, signal) {
|
|
43
|
-
const gwUrl = this.url;
|
|
43
|
+
const gwUrl = new URL(this.url.toString());
|
|
44
44
|
gwUrl.pathname = `/ipfs/${cid.toString()}`;
|
|
45
45
|
// necessary as not every gateway supports dag-cbor, but every should support
|
|
46
46
|
// sending raw block as-is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trustless-gateway.js","sourceRoot":"","sources":["../../../src/trustless-gateway/trustless-gateway.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,MAAM,OAAO,gBAAgB;IACX,GAAG,CAAK;IACxB;;;;;OAKG;IACH,SAAS,GAAG,CAAC,CAAA;IAEb;;;;;OAKG;IACH,OAAO,GAAG,CAAC,CAAA;IAEX;;;;OAIG;IACH,cAAc,GAAG,CAAC,CAAA;IAElB;;OAEG;IACH,UAAU,GAAG,CAAC,CAAA;IAEG,GAAG,CAAQ;IAE5B,YAAa,GAAiB,EAAE,MAAuB;QACrD,IAAI,CAAC,GAAG,GAAG,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QAClD,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,wCAAwC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC7F,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAE,GAAQ,EAAE,MAAoB;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAA;
|
|
1
|
+
{"version":3,"file":"trustless-gateway.js","sourceRoot":"","sources":["../../../src/trustless-gateway/trustless-gateway.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,MAAM,OAAO,gBAAgB;IACX,GAAG,CAAK;IACxB;;;;;OAKG;IACH,SAAS,GAAG,CAAC,CAAA;IAEb;;;;;OAKG;IACH,OAAO,GAAG,CAAC,CAAA;IAEX;;;;OAIG;IACH,cAAc,GAAG,CAAC,CAAA;IAElB;;OAEG;IACH,UAAU,GAAG,CAAC,CAAA;IAEG,GAAG,CAAQ;IAE5B,YAAa,GAAiB,EAAE,MAAuB;QACrD,IAAI,CAAC,GAAG,GAAG,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QAClD,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,wCAAwC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC7F,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAE,GAAQ,EAAE,MAAoB;QAC/C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC1C,KAAK,CAAC,QAAQ,GAAG,SAAS,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAA;QAE1C,6EAA6E;QAC7E,0BAA0B;QAC1B,KAAK,CAAC,MAAM,GAAG,aAAa,CAAA;QAE5B,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,iBAAiB,IAAI,CAAC,GAAG,6BAA6B,CAAC,CAAA;QACjH,CAAC;QAED,IAAI,CAAC;YACH,IAAI,CAAC,SAAS,EAAE,CAAA;YAChB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE;gBACxC,MAAM;gBACN,OAAO,EAAE;oBACT,iEAAiE;oBACjE,gBAAgB;oBACd,MAAM,EAAE,0BAA0B;iBACnC;gBACD,KAAK,EAAE,aAAa;aACrB,CAAC,CAAA;YAEF,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;YAExC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,IAAI,CAAC,OAAO,EAAE,CAAA;gBACd,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,iBAAiB,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;YACtF,CAAC;YACD,IAAI,CAAC,UAAU,EAAE,CAAA;YACjB,OAAO,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAA;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,qEAAqE;YACrE,yCAAyC;YACzC,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,iBAAiB,IAAI,CAAC,GAAG,cAAc,CAAC,CAAA;YAC3F,CAAC;YACD,IAAI,CAAC,OAAO,EAAE,CAAA;YACd,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,EAAE,CAAC,CAAA;QAC7D,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,WAAW;QACT;;;WAGG;QACH,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,CAAA;QACV,CAAC;QAED,IAAI,IAAI,CAAC,cAAc,GAAG,CAAC,EAAE,CAAC;YAC5B,wCAAwC;YACxC,OAAO,CAAC,QAAQ,CAAA;QAClB,CAAC;QAED;;;;;;;WAOG;QACH,OAAO,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAA;IAChE,CAAC;IAED;;OAEG;IACH,sBAAsB;QACpB,IAAI,CAAC,cAAc,EAAE,CAAA;IACvB,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helia/block-brokers",
|
|
3
|
-
"version": "2.0.3-
|
|
3
|
+
"version": "2.0.3-9ea934e",
|
|
4
4
|
"description": "Block brokers for Helia",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"homepage": "https://github.com/ipfs/helia/tree/main/packages/block-brokers#readme",
|
|
@@ -53,21 +53,22 @@
|
|
|
53
53
|
"test:electron-main": "aegir test -t electron-main"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@helia/bitswap": "0.0.0-
|
|
57
|
-
"@helia/interface": "4.1.0-
|
|
56
|
+
"@helia/bitswap": "0.0.0-9ea934e",
|
|
57
|
+
"@helia/interface": "4.1.0-9ea934e",
|
|
58
|
+
"@helia/utils": "0.1.0-9ea934e",
|
|
58
59
|
"@libp2p/interface": "^1.1.4",
|
|
59
60
|
"@libp2p/utils": "^5.2.6",
|
|
61
|
+
"@multiformats/multiaddr": "^12.2.1",
|
|
60
62
|
"@multiformats/multiaddr-matcher": "^1.2.0",
|
|
61
63
|
"@multiformats/multiaddr-to-uri": "^10.0.1",
|
|
62
64
|
"interface-blockstore": "^5.2.10",
|
|
65
|
+
"interface-store": "^5.1.8",
|
|
63
66
|
"multiformats": "^13.1.0",
|
|
64
|
-
"p-defer": "^4.0.0",
|
|
65
67
|
"progress-events": "^1.0.0"
|
|
66
68
|
},
|
|
67
69
|
"devDependencies": {
|
|
68
70
|
"@libp2p/logger": "^4.0.7",
|
|
69
71
|
"@libp2p/peer-id-factory": "^4.0.7",
|
|
70
|
-
"@multiformats/multiaddr": "^12.1.14",
|
|
71
72
|
"@multiformats/uri-to-multiaddr": "^8.0.0",
|
|
72
73
|
"@types/sinon": "^17.0.3",
|
|
73
74
|
"aegir": "^42.2.5",
|
package/src/bitswap.ts
CHANGED
|
@@ -72,8 +72,8 @@ class BitswapBlockBroker implements BlockBroker<BitswapWantBlockProgressEvents,
|
|
|
72
72
|
return this.bitswap.want(cid, options)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
const session =
|
|
75
|
+
createSession (options?: CreateSessionOptions<BitswapWantBlockProgressEvents>): BlockBroker<BitswapWantBlockProgressEvents, BitswapNotifyProgressEvents> {
|
|
76
|
+
const session = this.bitswap.createSession(options)
|
|
77
77
|
|
|
78
78
|
return {
|
|
79
79
|
announce: async (cid, block, options) => {
|
|
@@ -81,7 +81,7 @@ class BitswapBlockBroker implements BlockBroker<BitswapWantBlockProgressEvents,
|
|
|
81
81
|
},
|
|
82
82
|
|
|
83
83
|
retrieve: async (cid, options) => {
|
|
84
|
-
return session.
|
|
84
|
+
return session.retrieve(cid, options)
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
}
|
|
@@ -1,25 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PeerQueue } from '@libp2p/utils/peer-queue'
|
|
3
|
-
import { isPrivateIp } from '@libp2p/utils/private-ip'
|
|
4
|
-
import { DNS, HTTP, HTTPS } from '@multiformats/multiaddr-matcher'
|
|
5
|
-
import { multiaddrToUri } from '@multiformats/multiaddr-to-uri'
|
|
6
|
-
import pDefer from 'p-defer'
|
|
1
|
+
import { createTrustlessGatewaySession } from './session.js'
|
|
7
2
|
import { TrustlessGateway } from './trustless-gateway.js'
|
|
8
3
|
import { DEFAULT_TRUSTLESS_GATEWAYS } from './index.js'
|
|
9
4
|
import type { TrustlessGatewayBlockBrokerInit, TrustlessGatewayComponents, TrustlessGatewayGetBlockProgressEvents } from './index.js'
|
|
10
5
|
import type { Routing, BlockRetrievalOptions, BlockBroker, CreateSessionOptions } from '@helia/interface'
|
|
11
|
-
import type { Logger } from '@libp2p/interface'
|
|
6
|
+
import type { ComponentLogger, Logger } from '@libp2p/interface'
|
|
12
7
|
import type { CID } from 'multiformats/cid'
|
|
13
8
|
|
|
14
9
|
export interface CreateTrustlessGatewaySessionOptions extends CreateSessionOptions<TrustlessGatewayGetBlockProgressEvents> {
|
|
15
|
-
/**
|
|
16
|
-
* Specify the cache control header to send to the remote. 'only-if-cached'
|
|
17
|
-
* will prevent the gateway from fetching the content if they don't have it.
|
|
18
|
-
*
|
|
19
|
-
* @default only-if-cached
|
|
20
|
-
*/
|
|
21
|
-
cacheControl?: string
|
|
22
|
-
|
|
23
10
|
/**
|
|
24
11
|
* By default we will only connect to peers with HTTPS addresses, pass true
|
|
25
12
|
* to also connect to HTTP addresses.
|
|
@@ -46,10 +33,12 @@ export class TrustlessGatewayBlockBroker implements BlockBroker<TrustlessGateway
|
|
|
46
33
|
private readonly gateways: TrustlessGateway[]
|
|
47
34
|
private readonly routing: Routing
|
|
48
35
|
private readonly log: Logger
|
|
36
|
+
private readonly logger: ComponentLogger
|
|
49
37
|
|
|
50
38
|
constructor (components: TrustlessGatewayComponents, init: TrustlessGatewayBlockBrokerInit = {}) {
|
|
51
39
|
this.components = components
|
|
52
40
|
this.log = components.logger.forComponent('helia:trustless-gateway-block-broker')
|
|
41
|
+
this.logger = components.logger
|
|
53
42
|
this.routing = components.routing
|
|
54
43
|
this.gateways = (init.gateways ?? DEFAULT_TRUSTLESS_GATEWAYS)
|
|
55
44
|
.map((gatewayOrUrl) => {
|
|
@@ -104,99 +93,10 @@ export class TrustlessGatewayBlockBroker implements BlockBroker<TrustlessGateway
|
|
|
104
93
|
}
|
|
105
94
|
}
|
|
106
95
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const broker = new TrustlessGatewayBlockBroker(this.components, {
|
|
113
|
-
gateways
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
this.log('finding transport-ipfs-gateway-http providers for cid %c', root)
|
|
117
|
-
|
|
118
|
-
const queue = new PeerQueue({
|
|
119
|
-
concurrency: options.providerQueryConcurrency ?? DEFAULT_SESSION_PROVIDER_QUERY_CONCURRENCY
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
Promise.resolve().then(async () => {
|
|
123
|
-
for await (const provider of this.routing.findProviders(root, options)) {
|
|
124
|
-
const httpAddresses = provider.multiaddrs.filter(ma => {
|
|
125
|
-
if (HTTPS.matches(ma) || (options.allowInsecure === true && HTTP.matches(ma))) {
|
|
126
|
-
if (options.allowLocal === true) {
|
|
127
|
-
return true
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (DNS.matches(ma)) {
|
|
131
|
-
return true
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return isPrivateIp(ma.toOptions().host) === false
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return false
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
if (httpAddresses.length === 0) {
|
|
141
|
-
continue
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
this.log('found transport-ipfs-gateway-http provider %p for cid %c', provider.id, root)
|
|
145
|
-
|
|
146
|
-
void queue.add(async () => {
|
|
147
|
-
for (const ma of httpAddresses) {
|
|
148
|
-
let uri: string | undefined
|
|
149
|
-
|
|
150
|
-
try {
|
|
151
|
-
// /ip4/x.x.x.x/tcp/31337/http
|
|
152
|
-
// /ip4/x.x.x.x/tcp/31337/https
|
|
153
|
-
// etc
|
|
154
|
-
uri = multiaddrToUri(ma)
|
|
155
|
-
|
|
156
|
-
const resource = `${uri}/ipfs/${root.toString()}?format=raw`
|
|
157
|
-
|
|
158
|
-
// make sure the peer is available - HEAD support doesn't seem to
|
|
159
|
-
// be very widely implemented so as long as the remote responds
|
|
160
|
-
// we are happy they are valid
|
|
161
|
-
// https://specs.ipfs.tech/http-gateways/trustless-gateway/#head-ipfs-cid-path-params
|
|
162
|
-
|
|
163
|
-
// in the future we should be able to request `${uri}/.well-known/libp2p-http
|
|
164
|
-
// and discover an IPFS gateway from $.protocols['/ipfs/gateway'].path
|
|
165
|
-
// in the response
|
|
166
|
-
// https://github.com/libp2p/specs/pull/508/files
|
|
167
|
-
const response = await fetch(resource, {
|
|
168
|
-
method: 'HEAD',
|
|
169
|
-
headers: {
|
|
170
|
-
Accept: 'application/vnd.ipld.raw',
|
|
171
|
-
'Cache-Control': options.cacheControl ?? 'only-if-cached'
|
|
172
|
-
},
|
|
173
|
-
signal: AbortSignal.timeout(options.providerQueryTimeout ?? DEFAULT_SESSION_PROVIDER_QUERY_TIMEOUT)
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
this.log('HEAD %s %d', resource, response.status)
|
|
177
|
-
gateways.push(uri)
|
|
178
|
-
broker.addGateway(uri)
|
|
179
|
-
|
|
180
|
-
this.log('found %d transport-ipfs-gateway-http providers for cid %c', gateways.length, root)
|
|
181
|
-
|
|
182
|
-
if (gateways.length === minProviders) {
|
|
183
|
-
deferred.resolve(broker)
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (gateways.length === maxProviders) {
|
|
187
|
-
queue.clear()
|
|
188
|
-
}
|
|
189
|
-
} catch (err: any) {
|
|
190
|
-
this.log.error('could not fetch %c from %a', root, uri ?? ma, err)
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
})
|
|
194
|
-
}
|
|
195
|
-
})
|
|
196
|
-
.catch(err => {
|
|
197
|
-
this.log.error('error creating session for %c', root, err)
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
return deferred.promise
|
|
96
|
+
createSession (options: CreateTrustlessGatewaySessionOptions = {}): BlockBroker<TrustlessGatewayGetBlockProgressEvents> {
|
|
97
|
+
return createTrustlessGatewaySession({
|
|
98
|
+
logger: this.logger,
|
|
99
|
+
routing: this.routing
|
|
100
|
+
}, options)
|
|
201
101
|
}
|
|
202
102
|
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { AbstractSession } from '@helia/utils'
|
|
2
|
+
import { isPrivateIp } from '@libp2p/utils/private-ip'
|
|
3
|
+
import { DNS, HTTP, HTTPS } from '@multiformats/multiaddr-matcher'
|
|
4
|
+
import { multiaddrToUri } from '@multiformats/multiaddr-to-uri'
|
|
5
|
+
import { TrustlessGateway } from './trustless-gateway.js'
|
|
6
|
+
import type { CreateTrustlessGatewaySessionOptions } from './broker.js'
|
|
7
|
+
import type { TrustlessGatewayGetBlockProgressEvents } from './index.js'
|
|
8
|
+
import type { BlockRetrievalOptions, Routing } from '@helia/interface'
|
|
9
|
+
import type { ComponentLogger } from '@libp2p/interface'
|
|
10
|
+
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
11
|
+
import type { AbortOptions } from 'interface-store'
|
|
12
|
+
import type { CID } from 'multiformats/cid'
|
|
13
|
+
|
|
14
|
+
const DEFAULT_ALLOW_INSECURE = false
|
|
15
|
+
const DEFAULT_ALLOW_LOCAL = false
|
|
16
|
+
|
|
17
|
+
export interface TrustlessGatewaySessionComponents {
|
|
18
|
+
logger: ComponentLogger
|
|
19
|
+
routing: Routing
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
class TrustlessGatewaySession extends AbstractSession<TrustlessGateway, TrustlessGatewayGetBlockProgressEvents> {
|
|
23
|
+
private readonly routing: Routing
|
|
24
|
+
private readonly allowInsecure: boolean
|
|
25
|
+
private readonly allowLocal: boolean
|
|
26
|
+
|
|
27
|
+
constructor (components: TrustlessGatewaySessionComponents, init: CreateTrustlessGatewaySessionOptions) {
|
|
28
|
+
super(components, {
|
|
29
|
+
...init,
|
|
30
|
+
name: 'helia:trustless-gateway:session'
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
this.routing = components.routing
|
|
34
|
+
this.allowInsecure = init.allowInsecure ?? DEFAULT_ALLOW_INSECURE
|
|
35
|
+
this.allowLocal = init.allowLocal ?? DEFAULT_ALLOW_LOCAL
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async queryProvider (cid: CID, provider: TrustlessGateway, options: BlockRetrievalOptions): Promise<Uint8Array> {
|
|
39
|
+
this.log('fetching BLOCK for %c from %s', cid, provider.url)
|
|
40
|
+
|
|
41
|
+
const block = await provider.getRawBlock(cid, options.signal)
|
|
42
|
+
this.log.trace('got block for %c from %s', cid, provider.url)
|
|
43
|
+
|
|
44
|
+
await options.validateFn?.(block)
|
|
45
|
+
|
|
46
|
+
return block
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async * findNewProviders (cid: CID, options: AbortOptions = {}): AsyncGenerator<TrustlessGateway> {
|
|
50
|
+
for await (const provider of this.routing.findProviders(cid, options)) {
|
|
51
|
+
// require http(s) addresses
|
|
52
|
+
const httpAddresses = filterMultiaddrs(provider.multiaddrs, this.allowInsecure, this.allowLocal)
|
|
53
|
+
|
|
54
|
+
if (httpAddresses.length === 0) {
|
|
55
|
+
continue
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// take first address?
|
|
59
|
+
// /ip4/x.x.x.x/tcp/31337/http
|
|
60
|
+
// /ip4/x.x.x.x/tcp/31337/https
|
|
61
|
+
// etc
|
|
62
|
+
const uri = multiaddrToUri(httpAddresses[0])
|
|
63
|
+
|
|
64
|
+
this.log('found http-gateway provider %p %s for cid %c', provider.id, uri, cid)
|
|
65
|
+
yield new TrustlessGateway(uri, this.logger)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
toEvictionKey (provider: TrustlessGateway): Uint8Array | string {
|
|
70
|
+
return provider.url.toString()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
equals (providerA: TrustlessGateway, providerB: TrustlessGateway): boolean {
|
|
74
|
+
return providerA.url.toString() === providerB.url.toString()
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function filterMultiaddrs (multiaddrs: Multiaddr[], allowInsecure: boolean, allowLocal: boolean): Multiaddr[] {
|
|
79
|
+
return multiaddrs.filter(ma => {
|
|
80
|
+
if (HTTPS.matches(ma) || (allowInsecure && HTTP.matches(ma))) {
|
|
81
|
+
if (allowLocal) {
|
|
82
|
+
return true
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (DNS.matches(ma)) {
|
|
86
|
+
return true
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return isPrivateIp(ma.toOptions().host) === false
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return false
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function createTrustlessGatewaySession (components: TrustlessGatewaySessionComponents, init: CreateTrustlessGatewaySessionOptions): TrustlessGatewaySession {
|
|
97
|
+
return new TrustlessGatewaySession(components, init)
|
|
98
|
+
}
|
|
@@ -49,7 +49,7 @@ export class TrustlessGateway {
|
|
|
49
49
|
* https://specs.ipfs.tech/http-gateways/trustless-gateway/
|
|
50
50
|
*/
|
|
51
51
|
async getRawBlock (cid: CID, signal?: AbortSignal): Promise<Uint8Array> {
|
|
52
|
-
const gwUrl = this.url
|
|
52
|
+
const gwUrl = new URL(this.url.toString())
|
|
53
53
|
gwUrl.pathname = `/ipfs/${cid.toString()}`
|
|
54
54
|
|
|
55
55
|
// necessary as not every gateway supports dag-cbor, but every should support
|