Skip to content

Commit d2079aa

Browse files
committed
add subdomain support
1 parent 86b7e70 commit d2079aa

File tree

4 files changed

+41
-35
lines changed

4 files changed

+41
-35
lines changed

.github/workflows/npmRelease.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ jobs:
1515
node-version: '18.x'
1616
registry-url: 'https://registry.npmjs.org'
1717
- run: npm install
18+
- run: npm run test
1819
- run: npm run build
1920
- run: npm publish
2021
env:

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ipfs-race",
3-
"version": "0.1.7",
3+
"version": "0.2.0",
44
"description": "Resolve an IPFS path using multiple gateways and methods to get data the fastest.",
55
"main": "dist/index.js",
66
"scripts": {

src/resolve.ts

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,13 @@ interface ResolveOutput {
3232
* @param {string} uri - the uri on ipfs that needs to be resolved, it can follow any of the following formats...
3333
* - <CID>
3434
* - <CID>/<path>
35-
* - ipfs/<CID>
36-
* - ipfs/<CID>/path
37-
* - ipns/<CID>
38-
* - ipns/<CID>/path
39-
* - http(s)://<gateway domain>/ipfs/<CID>
40-
* - http(s)://<gateway domain>/ipfs/<CID>/<path>
41-
* - http(s)://<gateway domain>/ipns/<CID>
42-
* - http(s)://<gateway domain>/ipns/<CID>/<path>
43-
* - ipfs://<CID>
44-
* - ipfs://<CID>/<path>
45-
* - ipns://<CID>
46-
* - ipns://<CID>/<path>
35+
* - ip(f|n)s/<CID>
36+
* - ip(f|n)s/<CID>/path
37+
* - http(s)://<gateway domain>/ip(f|n)s/<CID>
38+
* - http(s)://<gateway domain>/ip(f|n)s/<CID>/<path>
39+
* - ip(f|n)s://<CID>
40+
* - ip(f|n)s://<CID>/<path>
41+
* - http(s)://<CID>.ip(f|n)s.<gateway domain>/<path>
4742
* - https(s)://<regular url> - this will resolve a http request for a generic url
4843
* @param options
4944
*/
@@ -110,6 +105,36 @@ async function resolve(uri: string, options?: ResolveOptions): Promise<ResolveOu
110105
gatewaySuffix = `/${protocol}/${uri}`;
111106
}
112107

108+
// check to see if a subdomain uri
109+
else if (isIPFS.ipfsSubdomain(uri) || isIPFS.ipnsSubdomain(uri)) {
110+
111+
// check to see if ipfs or ipns
112+
if (isIPFS.ipfsSubdomain(uri)) {
113+
protocol = "ipfs";
114+
} else if (isIPFS.ipnsSubdomain(uri)) {
115+
protocol = "ipns";
116+
}
117+
118+
// get everything to the left of the protocol for the CID
119+
let tmp = uri.split(`.${protocol}.`);
120+
let cid = tmp[0];
121+
122+
// remove the http or https if it exists
123+
if (cid.startsWith("https://")) {
124+
cid = cid.replace("https://", "");
125+
} else if ("http://") {
126+
cid = cid.replace("http://", "");
127+
}
128+
129+
// get everything to the right of the domain, this will be the path
130+
tmp = tmp[1].split("/");
131+
tmp.shift();
132+
const path = tmp.join("/");
133+
134+
// compile into the suffix
135+
gatewaySuffix = `/${protocol}/${cid}/${path}`;
136+
}
137+
113138
// check to see if uri is a link to a gateway and ipfs
114139
else if (isIPFS.ipfsUrl(uri) || isIPFS.ipnsUrl(uri)) {
115140

@@ -128,22 +153,7 @@ async function resolve(uri: string, options?: ResolveOptions): Promise<ResolveOu
128153
protocol = "ipns";
129154
}
130155

131-
if (isIPFS.path(cid)) {
132-
gatewaySuffix = cid
133-
} else {
134-
const response: Response = await _options.fetchOverride(uri, {
135-
method: "get",
136-
});
137-
138-
if (response.status >= 300 || response.status < 200) {
139-
throw new Error(`Url (${uri}) did not return a 2xx response and did not match a valid IPFS/IPNS format.`);
140-
}
141-
142-
return {
143-
response,
144-
urlResolvedFrom: uri,
145-
};
146-
}
156+
gatewaySuffix = cid
147157
}
148158

149159
// check to see if the link has the ipfs:// or ipns:// protocol/scheme
@@ -163,7 +173,6 @@ async function resolve(uri: string, options?: ResolveOptions): Promise<ResolveOu
163173
}
164174

165175
gatewaySuffix = `/${protocol}/${cidWithOptionalPath}`;
166-
167176
}
168177

169178
// when all other methods fail, it is a regular URL and will be requested like normal

src/test.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ describe("Tests the ipfs-race library.", () => {
1212
const testUrlSubdomainWithPath = "https://bafybeih3dhxuzle4nt2rirdezbssc43vjrws2f7zocbzrsgjqe5zo3b23e.ipfs.nftstorage.link/10896.json";
1313
const testUrlSubdomainWithResult = {"name":"Iron Pigeon #10896 1st Edition","symbol":"XPTCS","description":"Mike Tyson brings his love for pigeons to the Metaverse by making them the second set in the Ex Populus Trading Card System. Mint your own Iron Pigeon and evolve your way to Legendary in the game Final Form. Learn more about Final Form: https://expopulus.com/games/final-form","seller_fee_basis_points":1000,"image":"https://ipfs.io/ipfs/QmbrCdrecFDeuDKukaC97vb3uZ5ioHiWzzb1VncLDKhFGA","external_url":"https://ironpigeons.expopulus.com","attributes":[{"trait_type":"Rarity","value":"rare"},{"trait_type":"Power","value":"286"},{"trait_type":"Health","value":"healthy"},{"trait_type":"Attack","value":"formidable"},{"trait_type":"Ability 1","value":"Evade"},{"trait_type":"House","value":"Machines"},{"trait_type":"Set Name","value":"Iron Pigeons"},{"trait_type":"Set Number","value":"2"},{"trait_type":"Edition","value":"1st Edition"},{"trait_type":"Card Number","value":"10896"},{"trait_type":"Body","value":"shredded white"},{"trait_type":"Costume","value":"high-top fade"},{"trait_type":"Beak","value":"standard"},{"trait_type":"Eyes","value":"pink"},{"trait_type":"Background","value":"blue"}],"collection":{"name":"Iron Pigeons","family":"Ex Populus Trading Card System"},"properties":{"creators":[{"address":"3NXTh2Bw64a72RGGJ2mh8V7YEW2jERGdESjqxyvBoXo1","share":35},{"address":"39gMkx283UsuKNt5ogETWdHHaGyBwbh8sU5cKAEQjU2w","share":15},{"address":"4MnG71K4EXDHFysnnftV9YLDhnUjfxY5jTE34QAx4Pho","share":50}],"files":[{"uri":"https://ipfs.io/ipfs/QmbrCdrecFDeuDKukaC97vb3uZ5ioHiWzzb1VncLDKhFGA","type":"image/png"},{"uri":"https://ipfs.io/ipfs/QmXT3yXQ6dEZawcGTwXjwQhTaDgKMwuTts6fU9S2jyyPoh","type":"image/png"},{"uri":"https://ipfs.io/ipfs/QmUCSep13eQCrNpAnQSwpadtJDgUW4D1CWUUooFYeUMUGt","type":"image/png"},{"uri":"https://ipfs.io/ipfs/QmY9KQYHTMxGHK7VizvmyqDFxR5LgRfEGjkJmuuax7nvVL","type":"image/png"}],"category":"image"}};
1414

15+
1516
it("cid with no path", async () => {
1617
const {response, urlResolvedFrom} = await resolve(testCidWithNoPath);
1718
expect(await response.json(), urlResolvedFrom).to.deep.equal(testCidWithNoPathResult);
@@ -47,11 +48,6 @@ describe("Tests the ipfs-race library.", () => {
4748
expect(await response.json(), urlResolvedFrom).to.deep.equal(testUrlSubdomainWithResult);
4849
});
4950

50-
it("test ipfs subdomain with no path", async () => {
51-
// const {response, urlResolvedFrom} = await resolve(testUrlSubdomainWithPath);
52-
// expect(await response.json(), urlResolvedFrom).to.deep.equal(testUrlSubdomainWithResult);
53-
});
54-
5551
it("check that each default ipfs gateway to be a valid url", () => {
5652
for (const url of defaultIpfsGateways) {
5753
expect(isValidHttpUrl(url)).to.be.true;

0 commit comments

Comments
 (0)