@helia/verified-fetch 5.1.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.min.js +52 -52
- package/dist/index.min.js.map +4 -4
- package/dist/src/index.d.ts +20 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/plugins/plugin-handle-unixfs.d.ts.map +1 -1
- package/dist/src/plugins/plugin-handle-unixfs.js +6 -6
- package/dist/src/plugins/plugin-handle-unixfs.js.map +1 -1
- package/dist/src/url-resolver.d.ts.map +1 -1
- package/dist/src/url-resolver.js +1 -2
- package/dist/src/url-resolver.js.map +1 -1
- package/dist/src/utils/error-to-response.d.ts +1 -1
- package/dist/src/utils/error-to-response.d.ts.map +1 -1
- package/dist/src/utils/error-to-response.js +13 -11
- package/dist/src/utils/error-to-response.js.map +1 -1
- package/dist/src/utils/get-range-header.d.ts +2 -1
- package/dist/src/utils/get-range-header.d.ts.map +1 -1
- package/dist/src/utils/get-range-header.js.map +1 -1
- package/dist/src/utils/parse-resource.d.ts +10 -0
- package/dist/src/utils/parse-resource.d.ts.map +1 -0
- package/dist/src/utils/parse-resource.js +52 -0
- package/dist/src/utils/parse-resource.js.map +1 -0
- package/dist/src/utils/responses.d.ts +14 -14
- package/dist/src/utils/responses.d.ts.map +1 -1
- package/dist/src/utils/responses.js +8 -3
- package/dist/src/utils/responses.js.map +1 -1
- package/dist/src/verified-fetch.d.ts +1 -0
- package/dist/src/verified-fetch.d.ts.map +1 -1
- package/dist/src/verified-fetch.js +94 -102
- package/dist/src/verified-fetch.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +20 -4
- package/src/plugins/plugin-handle-unixfs.ts +9 -8
- package/src/url-resolver.ts +1 -2
- package/src/utils/error-to-response.ts +14 -11
- package/src/utils/get-range-header.ts +2 -1
- package/src/utils/parse-resource.ts +62 -0
- package/src/utils/responses.ts +24 -19
- package/src/verified-fetch.ts +105 -110
- package/dist/src/utils/ipfs-path-to-url.d.ts +0 -16
- package/dist/src/utils/ipfs-path-to-url.d.ts.map +0 -1
- package/dist/src/utils/ipfs-path-to-url.js +0 -45
- package/dist/src/utils/ipfs-path-to-url.js.map +0 -1
- package/dist/src/utils/parse-url-string.d.ts +0 -23
- package/dist/src/utils/parse-url-string.d.ts.map +0 -1
- package/dist/src/utils/parse-url-string.js +0 -120
- package/dist/src/utils/parse-url-string.js.map +0 -1
- package/dist/src/utils/resource-to-cache-key.d.ts +0 -15
- package/dist/src/utils/resource-to-cache-key.d.ts.map +0 -1
- package/dist/src/utils/resource-to-cache-key.js +0 -27
- package/dist/src/utils/resource-to-cache-key.js.map +0 -1
- package/src/utils/ipfs-path-to-url.ts +0 -54
- package/src/utils/parse-url-string.ts +0 -165
- package/src/utils/resource-to-cache-key.ts +0 -30
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { InvalidParametersError } from '@libp2p/interface';
|
|
2
|
-
import { peerIdFromCID, peerIdFromString } from '@libp2p/peer-id';
|
|
3
|
-
import { CID } from 'multiformats/cid';
|
|
4
|
-
import { decodeDNSLinkLabel, isInlinedDnsLink } from "./dnslink-label.js";
|
|
5
|
-
import { ipfsPathToUrl, ipfsUrlToUrl } from "./ipfs-path-to-url.js";
|
|
6
|
-
export const SUBDOMAIN_GATEWAY_REGEX = /^(?<cidOrPeerIdOrDnsLink>[^/?]+)\.(?<protocol>ip[fn]s)\.([^/?]+)$/;
|
|
7
|
-
const CODEC_LIBP2P_KEY = 0x72;
|
|
8
|
-
function matchSubdomainGroupsGuard(groups) {
|
|
9
|
-
const protocol = groups?.protocol;
|
|
10
|
-
if (protocol !== 'ipfs' && protocol !== 'ipns') {
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
const cidOrPeerIdOrDnsLink = groups?.cidOrPeerIdOrDnsLink;
|
|
14
|
-
if (cidOrPeerIdOrDnsLink == null) {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* If the caller has passed a case-sensitive identifier (like a base58btc
|
|
21
|
-
* encoded CID or PeerId) in a case-insensitive location (like a subdomain),
|
|
22
|
-
* be nice and return the original identifier from the passed string
|
|
23
|
-
*/
|
|
24
|
-
function findOriginalCidOrPeer(needle, haystack) {
|
|
25
|
-
const start = haystack.toLowerCase().indexOf(needle);
|
|
26
|
-
if (start === -1) {
|
|
27
|
-
return needle;
|
|
28
|
-
}
|
|
29
|
-
return haystack.substring(start, start + needle.length);
|
|
30
|
-
}
|
|
31
|
-
function stringToUrl(urlString) {
|
|
32
|
-
if (urlString instanceof URL) {
|
|
33
|
-
return urlString;
|
|
34
|
-
}
|
|
35
|
-
// turn IPFS/IPNS path into gateway URL string
|
|
36
|
-
if (urlString.startsWith('/ipfs/') || urlString.startsWith('/ipns/')) {
|
|
37
|
-
urlString = ipfsPathToUrl(urlString);
|
|
38
|
-
}
|
|
39
|
-
// turn IPFS/IPNS URL into gateway URL string
|
|
40
|
-
if (urlString.startsWith('ipfs://') || urlString.startsWith('ipns://')) {
|
|
41
|
-
urlString = ipfsUrlToUrl(urlString);
|
|
42
|
-
}
|
|
43
|
-
if (urlString.startsWith('http://') || urlString.startsWith('https://')) {
|
|
44
|
-
return new URL(urlString);
|
|
45
|
-
}
|
|
46
|
-
throw new InvalidParametersError(`Invalid URL: ${urlString}`);
|
|
47
|
-
}
|
|
48
|
-
function toURL(urlString) {
|
|
49
|
-
// validate url
|
|
50
|
-
const url = stringToUrl(urlString);
|
|
51
|
-
// test for subdomain gateway URL
|
|
52
|
-
const subdomainMatch = url.hostname.match(SUBDOMAIN_GATEWAY_REGEX);
|
|
53
|
-
if (matchSubdomainGroupsGuard(subdomainMatch?.groups)) {
|
|
54
|
-
const groups = subdomainMatch.groups;
|
|
55
|
-
if (groups.protocol === 'ipns' && isInlinedDnsLink(groups.cidOrPeerIdOrDnsLink)) {
|
|
56
|
-
// decode inline dnslink domain if present
|
|
57
|
-
groups.cidOrPeerIdOrDnsLink = decodeDNSLinkLabel(groups.cidOrPeerIdOrDnsLink);
|
|
58
|
-
}
|
|
59
|
-
const cidOrPeerIdOrDnsLink = findOriginalCidOrPeer(groups.cidOrPeerIdOrDnsLink, urlString);
|
|
60
|
-
// parse url as not http(s):// - this is necessary because URL makes
|
|
61
|
-
// `.pathname` default to `/` for http URLs, even if no trailing slash was
|
|
62
|
-
// present in the string URL and we need to be able to round-trip the user's
|
|
63
|
-
// input while also maintaining a sane canonical URL for the resource. Phew.
|
|
64
|
-
const wat = new URL(`not-${urlString}`);
|
|
65
|
-
return new URL(`${groups.protocol}://${cidOrPeerIdOrDnsLink}${wat.pathname}${url.search}${url.hash}`);
|
|
66
|
-
}
|
|
67
|
-
// test for IPFS path gateway URL
|
|
68
|
-
if (url.pathname.startsWith('/ipfs/')) {
|
|
69
|
-
const parts = url.pathname.substring(6).split('/');
|
|
70
|
-
const cid = parts.shift();
|
|
71
|
-
if (cid == null) {
|
|
72
|
-
throw new InvalidParametersError(`Path gateway URL ${urlString} had no CID`);
|
|
73
|
-
}
|
|
74
|
-
return new URL(`ipfs://${cid}${url.pathname.replace(`/ipfs/${cid}`, '')}${url.search}${url.hash}`);
|
|
75
|
-
}
|
|
76
|
-
// test for IPNS path gateway URL
|
|
77
|
-
if (url.pathname.startsWith('/ipns/')) {
|
|
78
|
-
const parts = url.pathname.substring(6).split('/');
|
|
79
|
-
const name = parts.shift();
|
|
80
|
-
if (name == null) {
|
|
81
|
-
throw new InvalidParametersError(`Path gateway URL ${urlString} had no name`);
|
|
82
|
-
}
|
|
83
|
-
return new URL(`ipns://${name}${url.pathname.replace(`/ipns/${name}`, '')}${url.search}${url.hash}`);
|
|
84
|
-
}
|
|
85
|
-
throw new TypeError(`Invalid URL: ${urlString}, please use ipfs://, ipns://, or gateway URLs only`);
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Accepts the following url strings:
|
|
89
|
-
*
|
|
90
|
-
* - /ipfs/Qmfoo/path
|
|
91
|
-
* - /ipns/Qmfoo/path
|
|
92
|
-
* - ipfs://cid/path
|
|
93
|
-
* - ipns://name/path
|
|
94
|
-
* - http://cid.ipfs.example.com/path
|
|
95
|
-
* - http://name.ipns.example.com/path
|
|
96
|
-
* - http://example.com/ipfs/cid/path
|
|
97
|
-
* - http://example.com/ipns/name/path
|
|
98
|
-
*/
|
|
99
|
-
export function parseURLString(urlString) {
|
|
100
|
-
// validate url
|
|
101
|
-
const url = toURL(urlString);
|
|
102
|
-
// treat IPNS keys that do not parse as PeerIds as DNSLink
|
|
103
|
-
if (url.protocol === 'ipns:') {
|
|
104
|
-
try {
|
|
105
|
-
peerIdFromString(url.hostname);
|
|
106
|
-
}
|
|
107
|
-
catch {
|
|
108
|
-
url.protocol = 'dnslink:';
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
if (url.protocol === 'ipfs:') {
|
|
112
|
-
const cid = CID.parse(url.hostname);
|
|
113
|
-
// special case - peer id encoded as a CID
|
|
114
|
-
if (cid.code === CODEC_LIBP2P_KEY) {
|
|
115
|
-
return new URL(`ipns://${peerIdFromCID(cid)}${url.pathname}${url.search}${url.hash}`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return url;
|
|
119
|
-
}
|
|
120
|
-
//# sourceMappingURL=parse-url-string.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse-url-string.js","sourceRoot":"","sources":["../../../src/utils/parse-url-string.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { CID } from 'multiformats/cid';
|
|
2
|
-
/**
|
|
3
|
-
* Takes a resource and returns a session cache key as an IPFS or IPNS path with
|
|
4
|
-
* any trailing segments removed.
|
|
5
|
-
*
|
|
6
|
-
* E.g.
|
|
7
|
-
*
|
|
8
|
-
* - Qmfoo -> /ipfs/Qmfoo
|
|
9
|
-
* - https://Qmfoo.ipfs.gateway.org -> ipfs://Qmfoo
|
|
10
|
-
* - https://gateway.org/ipfs/Qmfoo -> ipfs://Qmfoo
|
|
11
|
-
* - https://gateway.org/ipfs/Qmfoo/bar.txt -> ipfs://Qmfoo
|
|
12
|
-
* - etc
|
|
13
|
-
*/
|
|
14
|
-
export declare function resourceToSessionCacheKey(url: string | CID): string;
|
|
15
|
-
//# sourceMappingURL=resource-to-cache-key.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resource-to-cache-key.d.ts","sourceRoot":"","sources":["../../../src/utils/resource-to-cache-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAGtC;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAE,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,MAAM,CAcpE"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { CID } from 'multiformats/cid';
|
|
2
|
-
import { parseURLString } from './parse-url-string.js';
|
|
3
|
-
/**
|
|
4
|
-
* Takes a resource and returns a session cache key as an IPFS or IPNS path with
|
|
5
|
-
* any trailing segments removed.
|
|
6
|
-
*
|
|
7
|
-
* E.g.
|
|
8
|
-
*
|
|
9
|
-
* - Qmfoo -> /ipfs/Qmfoo
|
|
10
|
-
* - https://Qmfoo.ipfs.gateway.org -> ipfs://Qmfoo
|
|
11
|
-
* - https://gateway.org/ipfs/Qmfoo -> ipfs://Qmfoo
|
|
12
|
-
* - https://gateway.org/ipfs/Qmfoo/bar.txt -> ipfs://Qmfoo
|
|
13
|
-
* - etc
|
|
14
|
-
*/
|
|
15
|
-
export function resourceToSessionCacheKey(url) {
|
|
16
|
-
const cid = CID.asCID(url);
|
|
17
|
-
if (cid != null) {
|
|
18
|
-
return `ipfs://${cid}`;
|
|
19
|
-
}
|
|
20
|
-
try {
|
|
21
|
-
return `ipfs://${CID.parse(url.toString())}`;
|
|
22
|
-
}
|
|
23
|
-
catch { }
|
|
24
|
-
const { protocol, host } = parseURLString(url.toString());
|
|
25
|
-
return `${protocol}//${host}`;
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=resource-to-cache-key.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resource-to-cache-key.js","sourceRoot":"","sources":["../../../src/utils/resource-to-cache-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEtD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,yBAAyB,CAAE,GAAiB;IAC1D,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAE1B,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QAChB,OAAO,UAAU,GAAG,EAAE,CAAA;IACxB,CAAC;IAED,IAAI,CAAC;QACH,OAAO,UAAU,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAA;IAC9C,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;IAEzD,OAAO,GAAG,QAAQ,KAAK,IAAI,EAAE,CAAA;AAC/B,CAAC"}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { InvalidParametersError } from '@libp2p/interface'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Turns an IPFS or IPNS path into a HTTP URL. Path gateway syntax is used to
|
|
5
|
-
* preserve any case sensitivity
|
|
6
|
-
*
|
|
7
|
-
* - `/ipfs/cid` -> `https://example.org/ipfs/cid`
|
|
8
|
-
* - `/ipns/name` -> `https://example.org/ipns/name`
|
|
9
|
-
*/
|
|
10
|
-
export function ipfsPathToUrl (path: string): string {
|
|
11
|
-
if (!path.startsWith('/ipfs/') && !path.startsWith('/ipns/')) {
|
|
12
|
-
throw new InvalidParametersError(`Path ${path} did not start with /ipfs/ or /ipns/`)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// trim fragment
|
|
16
|
-
const fragmentIndex = path.indexOf('#')
|
|
17
|
-
let fragment = ''
|
|
18
|
-
|
|
19
|
-
if (fragmentIndex > -1) {
|
|
20
|
-
fragment = path.substring(fragmentIndex)
|
|
21
|
-
path = path.substring(0, fragmentIndex)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// trim query
|
|
25
|
-
const queryIndex = path.indexOf('?')
|
|
26
|
-
let query = ''
|
|
27
|
-
|
|
28
|
-
if (queryIndex > -1) {
|
|
29
|
-
query = path.substring(queryIndex)
|
|
30
|
-
path = path.substring(0, queryIndex)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const type = path.substring(1, 5)
|
|
34
|
-
const rest = path.substring(6)
|
|
35
|
-
|
|
36
|
-
return `https://example.org/${type}/${rest}${query}${fragment}`
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Turns an IPFS or IPNS URL into a HTTP URL. Path gateway syntax is used to
|
|
41
|
-
* preserve and case sensitivity
|
|
42
|
-
*
|
|
43
|
-
* `ipfs://cid` -> `https://example.org/ipfs/cid`
|
|
44
|
-
*/
|
|
45
|
-
export function ipfsUrlToUrl (url: string): string {
|
|
46
|
-
if (!url.startsWith('ipfs://') && !url.startsWith('ipns://')) {
|
|
47
|
-
throw new InvalidParametersError(`URL ${url} did not start with ipfs:// or ipns://`)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const type = url.substring(0, 4)
|
|
51
|
-
const rest = url.substring(7)
|
|
52
|
-
|
|
53
|
-
return `https://example.org/${type}/${rest}`
|
|
54
|
-
}
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { InvalidParametersError } from '@libp2p/interface'
|
|
2
|
-
import { peerIdFromCID, peerIdFromString } from '@libp2p/peer-id'
|
|
3
|
-
import { CID } from 'multiformats/cid'
|
|
4
|
-
import { decodeDNSLinkLabel, isInlinedDnsLink } from './dnslink-label.ts'
|
|
5
|
-
import { ipfsPathToUrl, ipfsUrlToUrl } from './ipfs-path-to-url.ts'
|
|
6
|
-
|
|
7
|
-
interface SubdomainMatchGroups {
|
|
8
|
-
protocol: 'ipfs' | 'ipns'
|
|
9
|
-
cidOrPeerIdOrDnsLink: string
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export const SUBDOMAIN_GATEWAY_REGEX = /^(?<cidOrPeerIdOrDnsLink>[^/?]+)\.(?<protocol>ip[fn]s)\.([^/?]+)$/
|
|
13
|
-
const CODEC_LIBP2P_KEY = 0x72
|
|
14
|
-
|
|
15
|
-
function matchSubdomainGroupsGuard (groups?: null | { [key in string]: string; } | SubdomainMatchGroups): groups is SubdomainMatchGroups {
|
|
16
|
-
const protocol = groups?.protocol
|
|
17
|
-
|
|
18
|
-
if (protocol !== 'ipfs' && protocol !== 'ipns') {
|
|
19
|
-
return false
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const cidOrPeerIdOrDnsLink = groups?.cidOrPeerIdOrDnsLink
|
|
23
|
-
|
|
24
|
-
if (cidOrPeerIdOrDnsLink == null) {
|
|
25
|
-
return false
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return true
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface ParsedURL {
|
|
32
|
-
url: URL,
|
|
33
|
-
protocol: 'ipfs' | 'ipns'
|
|
34
|
-
cidOrPeerIdOrDnsLink: string
|
|
35
|
-
path: string[]
|
|
36
|
-
query: Record<string, any>
|
|
37
|
-
fragment: string
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* If the caller has passed a case-sensitive identifier (like a base58btc
|
|
42
|
-
* encoded CID or PeerId) in a case-insensitive location (like a subdomain),
|
|
43
|
-
* be nice and return the original identifier from the passed string
|
|
44
|
-
*/
|
|
45
|
-
function findOriginalCidOrPeer (needle: string, haystack: string): string {
|
|
46
|
-
const start = haystack.toLowerCase().indexOf(needle)
|
|
47
|
-
|
|
48
|
-
if (start === -1) {
|
|
49
|
-
return needle
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return haystack.substring(start, start + needle.length)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function stringToUrl (urlString: string | URL): URL {
|
|
56
|
-
if (urlString instanceof URL) {
|
|
57
|
-
return urlString
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// turn IPFS/IPNS path into gateway URL string
|
|
61
|
-
if (urlString.startsWith('/ipfs/') || urlString.startsWith('/ipns/')) {
|
|
62
|
-
urlString = ipfsPathToUrl(urlString)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// turn IPFS/IPNS URL into gateway URL string
|
|
66
|
-
if (urlString.startsWith('ipfs://') || urlString.startsWith('ipns://')) {
|
|
67
|
-
urlString = ipfsUrlToUrl(urlString)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (urlString.startsWith('http://') || urlString.startsWith('https://')) {
|
|
71
|
-
return new URL(urlString)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
throw new InvalidParametersError(`Invalid URL: ${urlString}`)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function toURL (urlString: string): URL {
|
|
78
|
-
// validate url
|
|
79
|
-
const url = stringToUrl(urlString)
|
|
80
|
-
|
|
81
|
-
// test for subdomain gateway URL
|
|
82
|
-
const subdomainMatch = url.hostname.match(SUBDOMAIN_GATEWAY_REGEX)
|
|
83
|
-
|
|
84
|
-
if (matchSubdomainGroupsGuard(subdomainMatch?.groups)) {
|
|
85
|
-
const groups = subdomainMatch.groups
|
|
86
|
-
|
|
87
|
-
if (groups.protocol === 'ipns' && isInlinedDnsLink(groups.cidOrPeerIdOrDnsLink)) {
|
|
88
|
-
// decode inline dnslink domain if present
|
|
89
|
-
groups.cidOrPeerIdOrDnsLink = decodeDNSLinkLabel(groups.cidOrPeerIdOrDnsLink)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const cidOrPeerIdOrDnsLink = findOriginalCidOrPeer(groups.cidOrPeerIdOrDnsLink, urlString)
|
|
93
|
-
|
|
94
|
-
// parse url as not http(s):// - this is necessary because URL makes
|
|
95
|
-
// `.pathname` default to `/` for http URLs, even if no trailing slash was
|
|
96
|
-
// present in the string URL and we need to be able to round-trip the user's
|
|
97
|
-
// input while also maintaining a sane canonical URL for the resource. Phew.
|
|
98
|
-
const wat = new URL(`not-${urlString}`)
|
|
99
|
-
|
|
100
|
-
return new URL(`${groups.protocol}://${cidOrPeerIdOrDnsLink}${wat.pathname}${url.search}${url.hash}`)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// test for IPFS path gateway URL
|
|
104
|
-
if (url.pathname.startsWith('/ipfs/')) {
|
|
105
|
-
const parts = url.pathname.substring(6).split('/')
|
|
106
|
-
const cid = parts.shift()
|
|
107
|
-
|
|
108
|
-
if (cid == null) {
|
|
109
|
-
throw new InvalidParametersError(`Path gateway URL ${urlString} had no CID`)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return new URL(`ipfs://${cid}${url.pathname.replace(`/ipfs/${cid}`, '')}${url.search}${url.hash}`)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// test for IPNS path gateway URL
|
|
116
|
-
if (url.pathname.startsWith('/ipns/')) {
|
|
117
|
-
const parts = url.pathname.substring(6).split('/')
|
|
118
|
-
const name = parts.shift()
|
|
119
|
-
|
|
120
|
-
if (name == null) {
|
|
121
|
-
throw new InvalidParametersError(`Path gateway URL ${urlString} had no name`)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return new URL(`ipns://${name}${url.pathname.replace(`/ipns/${name}`, '')}${url.search}${url.hash}`)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
throw new TypeError(`Invalid URL: ${urlString}, please use ipfs://, ipns://, or gateway URLs only`)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Accepts the following url strings:
|
|
132
|
-
*
|
|
133
|
-
* - /ipfs/Qmfoo/path
|
|
134
|
-
* - /ipns/Qmfoo/path
|
|
135
|
-
* - ipfs://cid/path
|
|
136
|
-
* - ipns://name/path
|
|
137
|
-
* - http://cid.ipfs.example.com/path
|
|
138
|
-
* - http://name.ipns.example.com/path
|
|
139
|
-
* - http://example.com/ipfs/cid/path
|
|
140
|
-
* - http://example.com/ipns/name/path
|
|
141
|
-
*/
|
|
142
|
-
export function parseURLString (urlString: string): URL {
|
|
143
|
-
// validate url
|
|
144
|
-
const url = toURL(urlString)
|
|
145
|
-
|
|
146
|
-
// treat IPNS keys that do not parse as PeerIds as DNSLink
|
|
147
|
-
if (url.protocol === 'ipns:') {
|
|
148
|
-
try {
|
|
149
|
-
peerIdFromString(url.hostname)
|
|
150
|
-
} catch {
|
|
151
|
-
url.protocol = 'dnslink:'
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (url.protocol === 'ipfs:') {
|
|
156
|
-
const cid = CID.parse(url.hostname)
|
|
157
|
-
|
|
158
|
-
// special case - peer id encoded as a CID
|
|
159
|
-
if (cid.code === CODEC_LIBP2P_KEY) {
|
|
160
|
-
return new URL(`ipns://${peerIdFromCID(cid)}${url.pathname}${url.search}${url.hash}`)
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return url
|
|
165
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { CID } from 'multiformats/cid'
|
|
2
|
-
import { parseURLString } from './parse-url-string.js'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Takes a resource and returns a session cache key as an IPFS or IPNS path with
|
|
6
|
-
* any trailing segments removed.
|
|
7
|
-
*
|
|
8
|
-
* E.g.
|
|
9
|
-
*
|
|
10
|
-
* - Qmfoo -> /ipfs/Qmfoo
|
|
11
|
-
* - https://Qmfoo.ipfs.gateway.org -> ipfs://Qmfoo
|
|
12
|
-
* - https://gateway.org/ipfs/Qmfoo -> ipfs://Qmfoo
|
|
13
|
-
* - https://gateway.org/ipfs/Qmfoo/bar.txt -> ipfs://Qmfoo
|
|
14
|
-
* - etc
|
|
15
|
-
*/
|
|
16
|
-
export function resourceToSessionCacheKey (url: string | CID): string {
|
|
17
|
-
const cid = CID.asCID(url)
|
|
18
|
-
|
|
19
|
-
if (cid != null) {
|
|
20
|
-
return `ipfs://${cid}`
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
return `ipfs://${CID.parse(url.toString())}`
|
|
25
|
-
} catch {}
|
|
26
|
-
|
|
27
|
-
const { protocol, host } = parseURLString(url.toString())
|
|
28
|
-
|
|
29
|
-
return `${protocol}//${host}`
|
|
30
|
-
}
|