@helia/verified-fetch 1.1.0 → 1.1.2
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-url-string.d.ts","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAEtC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,4BAA4B,EAAE,qBAAqB,EAAiB,MAAM,aAAa,CAAA;AAC9H,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAItD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,eAAe,CAAA;CACxB;AACD,MAAM,WAAW,qBAAsB,SAAQ,eAAe,CAAC,qBAAqB,GAAG,iBAAiB,GAAG,4BAA4B,CAAC;CAEvI;AAED,MAAM,WAAW,cAAe,SAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACtE,MAAM,CAAC,EAAE,sBAAsB,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,GAAG,CAAA;IACR,KAAK,EAAE,cAAc,CAAA;CACtB;
|
|
1
|
+
{"version":3,"file":"parse-url-string.d.ts","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAEtC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,4BAA4B,EAAE,qBAAqB,EAAiB,MAAM,aAAa,CAAA;AAC9H,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAItD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,eAAe,CAAA;CACxB;AACD,MAAM,WAAW,qBAAsB,SAAQ,eAAe,CAAC,qBAAqB,GAAG,iBAAiB,GAAG,4BAA4B,CAAC;CAEvI;AAED,MAAM,WAAW,cAAe,SAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACtE,MAAM,CAAC,EAAE,sBAAsB,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,GAAG,CAAA;IACR,KAAK,EAAE,cAAc,CAAA;CACtB;AA+CD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAkGxJ"}
|
|
@@ -5,7 +5,7 @@ const ipnsCache = new TLRU(1000);
|
|
|
5
5
|
const URL_REGEX = /^(?<protocol>ip[fn]s):\/\/(?<cidOrPeerIdOrDnsLink>[^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/;
|
|
6
6
|
const PATH_REGEX = /^\/(?<protocol>ip[fn]s)\/(?<cidOrPeerIdOrDnsLink>[^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/;
|
|
7
7
|
const PATH_GATEWAY_REGEX = /^https?:\/\/(.*[^/])\/(?<protocol>ip[fn]s)\/(?<cidOrPeerIdOrDnsLink>[^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/;
|
|
8
|
-
const SUBDOMAIN_GATEWAY_REGEX = /^https?:\/\/(?<cidOrPeerIdOrDnsLink>[
|
|
8
|
+
const SUBDOMAIN_GATEWAY_REGEX = /^https?:\/\/(?<cidOrPeerIdOrDnsLink>[^/?]+)\.(?<protocol>ip[fn]s)\.([^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/;
|
|
9
9
|
function matchURLString(urlString) {
|
|
10
10
|
for (const pattern of [URL_REGEX, PATH_REGEX, PATH_GATEWAY_REGEX, SUBDOMAIN_GATEWAY_REGEX]) {
|
|
11
11
|
const match = urlString.match(pattern);
|
|
@@ -15,6 +15,30 @@ function matchURLString(urlString) {
|
|
|
15
15
|
}
|
|
16
16
|
throw new TypeError(`Invalid URL: ${urlString}, please use ipfs://, ipns://, or gateway URLs only`);
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* For dnslinks see https://specs.ipfs.tech/http-gateways/subdomain-gateway/#host-request-header
|
|
20
|
+
* DNSLink names include . which means they must be inlined into a single DNS label to provide unique origin and work with wildcard TLS certificates.
|
|
21
|
+
*/
|
|
22
|
+
// DNS label can have up to 63 characters, consisting of alphanumeric
|
|
23
|
+
// characters or hyphens -, but it must not start or end with a hyphen.
|
|
24
|
+
const dnsLabelRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/;
|
|
25
|
+
/**
|
|
26
|
+
* Checks if label looks like inlined DNSLink.
|
|
27
|
+
* (https://specs.ipfs.tech/http-gateways/subdomain-gateway/#host-request-header)
|
|
28
|
+
*/
|
|
29
|
+
function isInlinedDnsLink(label) {
|
|
30
|
+
return dnsLabelRegex.test(label) && label.includes('-') && !label.includes('.');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* DNSLink label decoding
|
|
34
|
+
* * Every standalone - is replaced with .
|
|
35
|
+
* * Every remaining -- is replaced with -
|
|
36
|
+
*
|
|
37
|
+
* @example en-wikipedia--on--ipfs-org.ipns.example.net -> example.net/ipns/en.wikipedia-on-ipfs.org
|
|
38
|
+
*/
|
|
39
|
+
function dnsLinkLabelDecoder(linkLabel) {
|
|
40
|
+
return linkLabel.replace(/--/g, '%').replace(/-/g, '.').replace(/%/g, '-');
|
|
41
|
+
}
|
|
18
42
|
/**
|
|
19
43
|
* A function that parses ipfs:// and ipns:// URLs, returning an object with easily recognizable properties.
|
|
20
44
|
*
|
|
@@ -67,12 +91,17 @@ export async function parseUrlString({ urlString, ipns, logger }, options) {
|
|
|
67
91
|
}
|
|
68
92
|
}
|
|
69
93
|
if (cid == null) {
|
|
70
|
-
|
|
94
|
+
let decodedDnsLinkLabel = cidOrPeerIdOrDnsLink;
|
|
95
|
+
if (isInlinedDnsLink(cidOrPeerIdOrDnsLink)) {
|
|
96
|
+
decodedDnsLinkLabel = dnsLinkLabelDecoder(cidOrPeerIdOrDnsLink);
|
|
97
|
+
log.trace('decoded dnslink from "%s" to "%s"', cidOrPeerIdOrDnsLink, decodedDnsLinkLabel);
|
|
98
|
+
}
|
|
99
|
+
log.trace('Attempting to resolve DNSLink for %s', decodedDnsLinkLabel);
|
|
71
100
|
try {
|
|
72
|
-
resolveResult = await ipns.resolveDns(
|
|
101
|
+
resolveResult = await ipns.resolveDns(decodedDnsLinkLabel, { onProgress: options?.onProgress });
|
|
73
102
|
cid = resolveResult?.cid;
|
|
74
103
|
resolvedPath = resolveResult?.path;
|
|
75
|
-
log.trace('resolved %s to %c',
|
|
104
|
+
log.trace('resolved %s to %c', decodedDnsLinkLabel, cid);
|
|
76
105
|
ipnsCache.set(cidOrPeerIdOrDnsLink, resolveResult, 60 * 1000 * 2);
|
|
77
106
|
}
|
|
78
107
|
catch (err) {
|
|
@@ -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,CAAgB,IAAI,CAAC,CAAA;AAwB/C,MAAM,SAAS,GAAG,kGAAkG,CAAA;AACpH,MAAM,UAAU,GAAG,iGAAiG,CAAA;AACpH,MAAM,kBAAkB,GAAG,oHAAoH,CAAA;AAC/I,MAAM,uBAAuB,GAAG,
|
|
1
|
+
{"version":3,"file":"parse-url-string.js","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helia/verified-fetch",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "A fetch-like API for obtaining verified & trustless IPFS content on the web",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"homepage": "https://github.com/ipfs/helia-verified-fetch/tree/main/packages/verified-fetch#readme",
|
|
@@ -33,7 +33,7 @@ export interface ParsedUrlStringResults {
|
|
|
33
33
|
const URL_REGEX = /^(?<protocol>ip[fn]s):\/\/(?<cidOrPeerIdOrDnsLink>[^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/
|
|
34
34
|
const PATH_REGEX = /^\/(?<protocol>ip[fn]s)\/(?<cidOrPeerIdOrDnsLink>[^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/
|
|
35
35
|
const PATH_GATEWAY_REGEX = /^https?:\/\/(.*[^/])\/(?<protocol>ip[fn]s)\/(?<cidOrPeerIdOrDnsLink>[^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/
|
|
36
|
-
const SUBDOMAIN_GATEWAY_REGEX = /^https?:\/\/(?<cidOrPeerIdOrDnsLink>[
|
|
36
|
+
const SUBDOMAIN_GATEWAY_REGEX = /^https?:\/\/(?<cidOrPeerIdOrDnsLink>[^/?]+)\.(?<protocol>ip[fn]s)\.([^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/
|
|
37
37
|
|
|
38
38
|
function matchURLString (urlString: string): Record<string, string> {
|
|
39
39
|
for (const pattern of [URL_REGEX, PATH_REGEX, PATH_GATEWAY_REGEX, SUBDOMAIN_GATEWAY_REGEX]) {
|
|
@@ -47,6 +47,34 @@ function matchURLString (urlString: string): Record<string, string> {
|
|
|
47
47
|
throw new TypeError(`Invalid URL: ${urlString}, please use ipfs://, ipns://, or gateway URLs only`)
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* For dnslinks see https://specs.ipfs.tech/http-gateways/subdomain-gateway/#host-request-header
|
|
52
|
+
* DNSLink names include . which means they must be inlined into a single DNS label to provide unique origin and work with wildcard TLS certificates.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
// DNS label can have up to 63 characters, consisting of alphanumeric
|
|
56
|
+
// characters or hyphens -, but it must not start or end with a hyphen.
|
|
57
|
+
const dnsLabelRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Checks if label looks like inlined DNSLink.
|
|
61
|
+
* (https://specs.ipfs.tech/http-gateways/subdomain-gateway/#host-request-header)
|
|
62
|
+
*/
|
|
63
|
+
function isInlinedDnsLink (label: string): boolean {
|
|
64
|
+
return dnsLabelRegex.test(label) && label.includes('-') && !label.includes('.')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* DNSLink label decoding
|
|
69
|
+
* * Every standalone - is replaced with .
|
|
70
|
+
* * Every remaining -- is replaced with -
|
|
71
|
+
*
|
|
72
|
+
* @example en-wikipedia--on--ipfs-org.ipns.example.net -> example.net/ipns/en.wikipedia-on-ipfs.org
|
|
73
|
+
*/
|
|
74
|
+
function dnsLinkLabelDecoder (linkLabel: string): string {
|
|
75
|
+
return linkLabel.replace(/--/g, '%').replace(/-/g, '.').replace(/%/g, '-')
|
|
76
|
+
}
|
|
77
|
+
|
|
50
78
|
/**
|
|
51
79
|
* A function that parses ipfs:// and ipns:// URLs, returning an object with easily recognizable properties.
|
|
52
80
|
*
|
|
@@ -80,7 +108,6 @@ export async function parseUrlString ({ urlString, ipns, logger }: ParseUrlStrin
|
|
|
80
108
|
// protocol is ipns
|
|
81
109
|
log.trace('Attempting to resolve PeerId for %s', cidOrPeerIdOrDnsLink)
|
|
82
110
|
let peerId = null
|
|
83
|
-
|
|
84
111
|
try {
|
|
85
112
|
peerId = peerIdFromString(cidOrPeerIdOrDnsLink)
|
|
86
113
|
resolveResult = await ipns.resolve(peerId, { onProgress: options?.onProgress })
|
|
@@ -99,13 +126,18 @@ export async function parseUrlString ({ urlString, ipns, logger }: ParseUrlStrin
|
|
|
99
126
|
}
|
|
100
127
|
|
|
101
128
|
if (cid == null) {
|
|
102
|
-
|
|
129
|
+
let decodedDnsLinkLabel = cidOrPeerIdOrDnsLink
|
|
130
|
+
if (isInlinedDnsLink(cidOrPeerIdOrDnsLink)) {
|
|
131
|
+
decodedDnsLinkLabel = dnsLinkLabelDecoder(cidOrPeerIdOrDnsLink)
|
|
132
|
+
log.trace('decoded dnslink from "%s" to "%s"', cidOrPeerIdOrDnsLink, decodedDnsLinkLabel)
|
|
133
|
+
}
|
|
134
|
+
log.trace('Attempting to resolve DNSLink for %s', decodedDnsLinkLabel)
|
|
103
135
|
|
|
104
136
|
try {
|
|
105
|
-
resolveResult = await ipns.resolveDns(
|
|
137
|
+
resolveResult = await ipns.resolveDns(decodedDnsLinkLabel, { onProgress: options?.onProgress })
|
|
106
138
|
cid = resolveResult?.cid
|
|
107
139
|
resolvedPath = resolveResult?.path
|
|
108
|
-
log.trace('resolved %s to %c',
|
|
140
|
+
log.trace('resolved %s to %c', decodedDnsLinkLabel, cid)
|
|
109
141
|
ipnsCache.set(cidOrPeerIdOrDnsLink, resolveResult, 60 * 1000 * 2)
|
|
110
142
|
} catch (err: any) {
|
|
111
143
|
log.error('Could not resolve DnsLink for "%s"', cidOrPeerIdOrDnsLink, err)
|