Skip to content

Commit 22d001d

Browse files
authored
feat: support subdomains in isIPFS.url(url) (#32)
* feat: support DNSLink subdomains This change adds support for DNSLink subdomains on localhost gateway (ipfs/kubo#6096) Example: en.wikipedia-on-ipfs.org.ipfs.localhost:8080 BREAKING CHANGE: `isIPFS.subdomain` now returns true for <domain.tld>.ipns.localhost BREAKING CHANGE: `isIPFS.subdomainPattern` changed * test: support peer multiaddr with /p2p/ Context: libp2p/libp2p#79 * fix: explicitly ignore URL param and hash .url and .path now return true when validating: https://ipfs.io/ipfs/<CID>?filename=name.png#foo * refactor: simplify dnslinkSubdomain License: MIT Signed-off-by: Marcin Rataj <[email protected]> * fix: url() check should include subdomain() When .url was created we only had path gateways. When .subdomain was added, we did not update .url to test for subdomain gateways, which in the long run will confuse people and feels like a bug. Let's fix this: .url() will now check for both subdomain and path gateways #32 (comment) BREAKING CHANGE: .url(url) now returns true if .subdomain(url) is true * refactor: merge DNSLink check into ipnsSubdomain() This makes subdomain checks follow what path gateway checks do, removing confusion. In both cases (IPNS and DNSLink) user needs to perform online record check, so this is just a handy way of detecting potential matches. * docs: update examples * refactor: switch to iso-url * refactor: lint-package-json * chore: update deps License: MIT Signed-off-by: Marcin Rataj <[email protected]>
1 parent 3823a89 commit 22d001d

8 files changed

+195
-83
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@ node_modules
3838

3939
dist
4040
lib
41+
docs

README.md

+26-10
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ $ npm install --save is-ipfs
2323
The code published to npm that gets loaded on require is in fact an ES5 transpiled version with the right shims added. This means that you can require it and use with your favorite bundler without having to adjust asset management process.
2424

2525
```js
26-
var isIPFS = require('is-ipfs')
26+
const isIPFS = require('is-ipfs')
2727
```
2828

2929

@@ -53,18 +53,23 @@ isIPFS.base32cid('bafybeie5gq4jxvzmsym6hjlwxej4rwdoxt7wadqvmmwbqi7r27fclha2va')
5353
isIPFS.base32cid('QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o') // false
5454

5555
isIPFS.url('https://ipfs.io/ipfs/QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o') // true
56+
isIPFS.url('https://ipfs.io/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR?filename=guardian.jpg') // true
5657
isIPFS.url('https://ipfs.io/ipns/github.com') // true
58+
isIPFS.url('https://bafybeie5gq4jxvzmsym6hjlwxej4rwdoxt7wadqvmmwbqi7r27fclha2va.ipfs.dweb.link') // true
59+
isIPFS.url('http://en.wikipedia-on-ipfs.org.ipfs.localhost:8080') // true
5760
isIPFS.url('https://github.com/ipfs/js-ipfs/blob/master/README.md') // false
5861
isIPFS.url('https://google.com') // false
5962

6063
isIPFS.path('/ipfs/QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o') // true
64+
isIPFS.path('/ipfs/QmbcBPAwCDxRMB1Qe7CRQmxdrTSkxKwM9y6rZw2FjGtbsb/?weird-filename=test.jpg') // true
6165
isIPFS.path('/ipns/github.com') // true
6266
isIPFS.path('/ipfs/js-ipfs/blob/master/README.md') // false
6367

6468
isIPFS.urlOrPath('https://ipfs.io/ipfs/QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o') // true
6569
isIPFS.urlOrPath('https://ipfs.io/ipns/github.com') // true
6670
isIPFS.urlOrPath('/ipfs/QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o') // true
6771
isIPFS.urlOrPath('/ipns/github.com') // true
72+
isIPFS.urlOrPath('https://bafybeie5gq4jxvzmsym6hjlwxej4rwdoxt7wadqvmmwbqi7r27fclha2va.ipfs.dweb.link') // true
6873
isIPFS.urlOrPath('https://google.com') // false
6974

7075
isIPFS.ipfsUrl('https://ipfs.io/ipfs/QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o') // true
@@ -96,17 +101,19 @@ isIPFS.ipfsSubdomain('http://bafybeie5gq4jxvzmsym6hjlwxej4rwdoxt7wadqvmmwbqi7r27
96101
isIPFS.ipnsSubdomain('http://bafybeiabc2xofh6tdi6vutusorpumwcikw3hf3st4ecjugo6j52f6xwc6q.ipns.dweb.link') // true
97102
isIPFS.ipnsSubdomain('http://bafybeiabc2xofh6tdi6vutusorpumwcikw3hf3st4ecjugo6j52f6xwc6q.dweb.link') // false
98103
isIPFS.ipnsSubdomain('http://QmcNioXSC1bfJj1dcFErhUfyjFzoX2HodkRccsFFVJJvg8.ipns.dweb.link') // false
99-
isIPFS.ipnsSubdomain('http://foo-bar.ipns.dweb.link') // false (not a PeerID)
104+
isIPFS.ipnsSubdomain('http://en.wikipedia-on-ipfs.org.ipns.localhost:8080') // true (assuming DNSLink)
105+
isIPFS.ipnsSubdomain('http://hostname-without-tld.ipns.dweb.link') // false (missing TLD)
100106

101107
isIPFS.multiaddr('/ip4/127.0.0.1/udp/1234') // true
102108
isIPFS.multiaddr('/ip4/127.0.0.1/udp/1234/http') // true
103109
isIPFS.multiaddr('/ip6/::1/udp/1234') // true
104110
isIPFS.multiaddr('ip6/::1/udp/1234') // false
105111
isIPFS.multiaddr('/yoloinvalid/::1/udp/1234') // false
106112

107-
isIPFS.peerMultiaddr('/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4') // true
108-
isIPFS.peerMultiaddr('/ip4/127.0.0.1/tcp/1234/ws/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj') // true
109-
isIPFS.peerMultiaddr('/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4/p2p-circuit/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj') // true
113+
isIPFS.peerMultiaddr('/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4') // true
114+
isIPFS.peerMultiaddr('/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4') // true (legacy notation)
115+
isIPFS.peerMultiaddr('/ip4/127.0.0.1/tcp/1234/ws/p2p/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj') // true
116+
isIPFS.peerMultiaddr('/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4/p2p-circuit/p2p/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj') // true
110117
isIPFS.peerMultiaddr('/ip4/127.0.0.1/udp/1234') // false
111118
```
112119

@@ -115,10 +122,9 @@ isIPFS.peerMultiaddr('/ip4/127.0.0.1/udp/1234') // false
115122
A suite of util methods that provides efficient validation.
116123

117124
Detection of IPFS Paths and identifiers in URLs is a two-stage process:
118-
1. `urlPattern`/`pathPattern`/`subdomainPattern` regex is applied to quickly identify potential candidates
125+
1. `pathPattern`/`pathGatewayPattern`/`subdomainGatewayPattern` regex is applied to quickly identify potential candidates
119126
2. proper CID validation is applied to remove false-positives
120127

121-
122128
## Content Identifiers
123129

124130
### `isIPFS.multihash(hash)`
@@ -178,15 +184,25 @@ Validated subdomain convention: `cidv1b32.ip(f|n)s.domain.tld`
178184

179185
### `isIPFS.subdomain(url)`
180186

181-
Returns `true` if the provided string includes a valid IPFS or IPNS subdomain or `false` otherwise.
187+
Returns `true` if the provided `url` string includes a valid IPFS, looks like IPNS/DNSLink subdomain or `false` otherwise.
182188

183189
### `isIPFS.ipfsSubdomain(url)`
184190

185-
Returns `true` if the provided string includes a valid IPFS subdomain or `false` otherwise.
191+
Returns `true` if the provided `url` string includes a valid IPFS subdomain (case-insensitive CIDv1) or `false` otherwise.
186192

187193
### `isIPFS.ipnsSubdomain(url)`
188194

189-
Returns `true` if the provided string includes a valid IPNS subdomain or `false` otherwise.
195+
Returns `true` if the provided `url` string looks like a valid IPNS subdomain
196+
(CIDv1 with `libp2p-key` multicodec or something that looks like a FQDN, for example `en.wikipedia-on-ipfs.org.ipns.localhost:8080`) or `false`
197+
otherwise.
198+
199+
**Note:** `ipnsSubdomain` method works in offline mode: it does not perform
200+
actual IPNS record lookup over DHT or other content routing method. It may
201+
return false-positives:
202+
203+
- To ensure IPNS record exists, make a call to `/api/v0/name/resolve?arg=<ipnsid>`
204+
- To ensure DNSLink exists, make a call to `/api/v0/dns?arg=<fqdn>`
205+
190206

191207
## Multiaddrs
192208

package.json

+37-25
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,67 @@
11
{
22
"name": "is-ipfs",
33
"version": "0.6.3",
4-
"description": "A set of utilities to help identify IPFS resources",
4+
"description": "A set of utilities to help identify IPFS resources on the web",
5+
"keywords": [
6+
"js-ipfs",
7+
"ipns",
8+
"gateway",
9+
"dnslink",
10+
"ipfs"
11+
],
12+
"homepage": "https://github.com/ipfs/is-ipfs",
13+
"bugs": {
14+
"url": "https://github.com/ipfs/is-ipfs/issues"
15+
},
16+
"license": "MIT",
17+
"author": "Francisco Dias <[email protected]> (http://franciscodias.net/)",
518
"leadMaintainer": "Marcin Rataj <[email protected]>",
19+
"files": [
20+
"src",
21+
"dist"
22+
],
623
"main": "src/index.js",
724
"browser": {
825
"fs": false
926
},
27+
"repository": {
28+
"type": "git",
29+
"url": "https://github.com/ipfs/is-ipfs.git"
30+
},
1031
"scripts": {
1132
"test:node": "aegir test --target node",
1233
"test:browser": "aegir test --target browser",
1334
"test": "aegir test",
14-
"lint": "aegir lint",
35+
"lint": "aegir lint && aegir lint-package-json",
1536
"release": "aegir release",
1637
"release-minor": "aegir release --type minor",
1738
"release-major": "aegir release --type major",
1839
"build": "aegir build",
1940
"coverage": "aegir coverage",
2041
"coverage-publish": "aegir coverage --upload"
2142
},
22-
"pre-commit": [
23-
"test",
24-
"lint"
25-
],
26-
"keywords": [
27-
"js-ipfs",
28-
"ipfs"
29-
],
30-
"author": "Francisco Dias <[email protected]> (http://franciscodias.net/)",
31-
"license": "MIT",
3243
"dependencies": {
3344
"bs58": "^4.0.1",
34-
"cids": "~0.7.0",
35-
"mafmt": "^7.0.0",
36-
"multiaddr": "^7.2.1",
37-
"multibase": "~0.6.0",
38-
"multihashes": "~0.4.13"
45+
"cids": "~0.8.0",
46+
"iso-url": "~0.4.7",
47+
"mafmt": "^7.1.0",
48+
"multiaddr": "^7.4.3",
49+
"multibase": "~0.7.0",
50+
"multihashes": "~0.4.19"
3951
},
4052
"devDependencies": {
41-
"aegir": "^20.5.0",
53+
"aegir": "^21.4.5",
4254
"chai": "^4.2.0",
4355
"pre-commit": "^1.2.2"
4456
},
45-
"repository": {
46-
"type": "git",
47-
"url": "https://github.com/ipfs/is-ipfs.git"
48-
},
49-
"bugs": {
50-
"url": "https://github.com/ipfs/is-ipfs/issues"
57+
"engines": {
58+
"node": ">=10.0.0",
59+
"npm": ">=6.0.0"
5160
},
52-
"homepage": "https://github.com/ipfs/is-ipfs",
61+
"pre-commit": [
62+
"test",
63+
"lint"
64+
],
5365
"contributors": [
5466
"Alan Shaw <[email protected]>",
5567
"David Dias <[email protected]>",

src/index.js

+48-25
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,20 @@ const multibase = require('multibase')
66
const Multiaddr = require('multiaddr')
77
const mafmt = require('mafmt')
88
const CID = require('cids')
9+
const { URL } = require('iso-url')
910

10-
const urlPattern = /^https?:\/\/[^/]+\/(ip(f|n)s)\/((\w+).*)/
11-
const pathPattern = /^\/(ip(f|n)s)\/((\w+).*)/
11+
const pathGatewayPattern = /^https?:\/\/[^/]+\/(ip[fn]s)\/([^/?#]+)/
12+
const pathPattern = /^\/(ip[fn]s)\/([^/?#]+)/
1213
const defaultProtocolMatch = 1
13-
const defaultHashMath = 4
14+
const defaultHashMath = 2
1415

15-
const fqdnPattern = /^https?:\/\/([^/]+)\.(ip(?:f|n)s)\.[^/]+/
16-
const fqdnHashMatch = 1
17-
const fqdnProtocolMatch = 2
16+
// CID, libp2p-key or DNSLink
17+
const subdomainGatewayPattern = /^https?:\/\/([^/]+)\.(ip[fn]s)\.[^/?]+/
18+
const subdomainIdMatch = 1
19+
const subdomainProtocolMatch = 2
20+
21+
// Fully qualified domain name (FQDN) that has an explicit .tld suffix
22+
const fqdnWithTld = /^(([a-z0-9]|[a-z0-9][a-z0-9-]*[a-z0-9])\.)+([a-z0-9]|[a-z0-9][a-z0-9-]*[a-z0-9])$/
1823

1924
function isMultihash (hash) {
2025
const formatted = convertToString(hash)
@@ -76,7 +81,7 @@ function isIpfs (input, pattern, protocolMatch = defaultProtocolMatch, hashMatch
7681

7782
let hash = match[hashMatch]
7883

79-
if (hash && pattern === fqdnPattern) {
84+
if (hash && pattern === subdomainGatewayPattern) {
8085
// when doing checks for subdomain context
8186
// ensure hash is case-insensitive
8287
// (browsers force-lowercase authority compotent anyway)
@@ -100,13 +105,24 @@ function isIpns (input, pattern, protocolMatch = defaultProtocolMatch, hashMatch
100105
return false
101106
}
102107

103-
if (hashMatch && pattern === fqdnPattern) {
104-
let hash = match[hashMatch]
108+
let ipnsId = match[hashMatch]
109+
110+
if (ipnsId && pattern === subdomainGatewayPattern) {
105111
// when doing checks for subdomain context
106-
// ensure hash is case-insensitive
112+
// ensure ipnsId is case-insensitive
107113
// (browsers force-lowercase authority compotent anyway)
108-
hash = hash.toLowerCase()
109-
return isCID(hash)
114+
ipnsId = ipnsId.toLowerCase()
115+
// Check if it is cidv1
116+
if (isCID(ipnsId)) return true
117+
// Check if it looks like FQDN
118+
try {
119+
// URL implementation in web browsers forces lowercase of the hostname
120+
const { hostname } = new URL(`http://${ipnsId}`) // eslint-disable-line no-new
121+
// Check if potential FQDN has an explicit TLD
122+
return fqdnWithTld.test(hostname)
123+
} catch (e) {
124+
return false
125+
}
110126
}
111127

112128
return true
@@ -128,27 +144,34 @@ function convertToString (input) {
128144
return false
129145
}
130146

131-
const ipfsSubdomain = (url) => isIpfs(url, fqdnPattern, fqdnProtocolMatch, fqdnHashMatch)
132-
const ipnsSubdomain = (url) => isIpns(url, fqdnPattern, fqdnProtocolMatch, fqdnHashMatch)
147+
const ipfsSubdomain = (url) => isIpfs(url, subdomainGatewayPattern, subdomainProtocolMatch, subdomainIdMatch)
148+
const ipnsSubdomain = (url) => isIpns(url, subdomainGatewayPattern, subdomainProtocolMatch, subdomainIdMatch)
149+
const subdomain = (url) => ipfsSubdomain(url) || ipnsSubdomain(url)
150+
151+
const ipfsUrl = (url) => isIpfs(url, pathGatewayPattern) || ipfsSubdomain(url)
152+
const ipnsUrl = (url) => isIpns(url, pathGatewayPattern) || ipnsSubdomain(url)
153+
const url = (url) => ipfsUrl(url) || ipnsUrl(url) || subdomain(url)
154+
155+
const path = (path) => isIpfs(path, pathPattern) || isIpns(path, pathPattern)
133156

134157
module.exports = {
135158
multihash: isMultihash,
136159
multiaddr: isMultiaddr,
137160
peerMultiaddr: isPeerMultiaddr,
138161
cid: isCID,
139162
base32cid: (cid) => (isMultibase(cid) === 'base32' && isCID(cid)),
140-
ipfsSubdomain: ipfsSubdomain,
141-
ipnsSubdomain: ipnsSubdomain,
142-
subdomain: (url) => (ipfsSubdomain(url) || ipnsSubdomain(url)),
143-
subdomainPattern: fqdnPattern,
144-
ipfsUrl: (url) => isIpfs(url, urlPattern),
145-
ipnsUrl: (url) => isIpns(url, urlPattern),
146-
url: (url) => (isIpfs(url, urlPattern) || isIpns(url, urlPattern)),
147-
urlPattern: urlPattern,
163+
ipfsSubdomain,
164+
ipnsSubdomain,
165+
subdomain,
166+
subdomainGatewayPattern,
167+
ipfsUrl,
168+
ipnsUrl,
169+
url,
170+
pathGatewayPattern: pathGatewayPattern,
148171
ipfsPath: (path) => isIpfs(path, pathPattern),
149172
ipnsPath: (path) => isIpns(path, pathPattern),
150-
path: (path) => (isIpfs(path, pathPattern) || isIpns(path, pathPattern)),
151-
pathPattern: pathPattern,
152-
urlOrPath: (x) => (isIpfs(x, urlPattern) || isIpns(x, urlPattern) || isIpfs(x, pathPattern) || isIpns(x, pathPattern)),
173+
path,
174+
pathPattern,
175+
urlOrPath: (x) => url(x) || path(x),
153176
cidPath: path => isString(path) && !isCID(path) && isIpfs(`/ipfs/${path}`, pathPattern)
154177
}

test/test-multiaddr.spec.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,27 @@ describe('ipfs peerMultiaddr', () => {
6767
// https://github.com/multiformats/js-mafmt/blob/v6.0.6/test/index.spec.js#L137
6868
const goodCircuit = [
6969
'/p2p-circuit',
70-
'/p2p-circuit/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj',
70+
'/p2p-circuit/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj', // /ipfs/ is legacy notation replaced with /p2p/
71+
'/p2p-circuit/p2p/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj',
7172
'/p2p-circuit/ip4/127.0.0.1/tcp/20008/ws/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj',
73+
'/p2p-circuit/ip4/127.0.0.1/tcp/20008/ws/p2p/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj',
7274
'/p2p-circuit/ip4/1.2.3.4/tcp/3456/ws/p2p-webrtc-star/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4',
75+
'/p2p-circuit/ip4/1.2.3.4/tcp/3456/ws/p2p-webrtc-star/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4',
76+
'/p2p-circuit/ip4/1.2.3.4/tcp/3456/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4',
7377
'/p2p-circuit/ip4/1.2.3.4/tcp/3456/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4',
7478
'/p2p-circuit/ip4/127.0.0.1/tcp/4002/ipfs/QmddWMcQX6orJGHpETYMyPgXrCXCtYANMFVDCvhKoDwLqA',
7579
'/p2p-circuit/ipfs/QmddWMcQX6orJGHpETYMyPgXrCXCtYANMFVDCvhKoDwLqA',
80+
'/p2p-circuit/p2p/QmddWMcQX6orJGHpETYMyPgXrCXCtYANMFVDCvhKoDwLqA',
7681
'/p2p-circuit/ip4/127.0.0.1/tcp/20008/ws/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj/' +
7782
'p2p-circuit/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj'
7883
]
7984
// https://github.com/multiformats/js-mafmt/blob/v6.0.6/test/index.spec.js#L157
8085
const validPeerMultiaddrs = [
8186
'/ip4/127.0.0.1/tcp/20008/ws/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj',
87+
'/ip4/127.0.0.1/tcp/20008/ws/p2p/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj',
88+
'/ip4/127.0.0.1/tcp/20008/ws/p2p/12D3KooWFB51PRY9BxcXSH6khFXw1BZeszeLDy7C8GciskqCTZn5', // ed25519+identity multihash
8289
'/ip4/1.2.3.4/tcp/3456/ws/p2p-webrtc-star/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4',
90+
'/ip4/1.2.3.4/tcp/3456/ws/p2p-webrtc-star/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4',
8391
'/ip4/1.2.3.4/tcp/3456/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4',
8492
'/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4/p2p-circuit',
8593
'/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4/p2p-circuit/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj'

test/test-path.spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ const expect = require('chai').expect
77

88
describe('ipfs path', () => {
99
it('isIPFS.ipfsPath should match an ipfs path', (done) => {
10-
const actual = isIPFS.ipfsPath('/ipfs/QmYHNYAaYK5hm3ZhZFx5W9H6xydKDGimjdgJMrMSdnctEm')
10+
const actual = isIPFS.ipfsPath('/ipfs/QmYHNYAaYK5hm3ZhZFx5W9H6xydKDGimjdgJMrMSdnctEm?arg=val#hash')
1111
expect(actual).to.equal(true)
1212
done()
1313
})
1414

1515
it('isIPFS.ipfsPath should match a complex ipfs path', (done) => {
16-
const actual = isIPFS.ipfsPath('/ipfs/QmeWz9YZEeNFXQhHg4PnR5ZiNr5isttgi5n1tc1eD5EfGU/content/index.html')
16+
const actual = isIPFS.ipfsPath('/ipfs/QmeWz9YZEeNFXQhHg4PnR5ZiNr5isttgi5n1tc1eD5EfGU/content/index.html?arg=val#hash')
1717
expect(actual).to.equal(true)
1818
done()
1919
})

0 commit comments

Comments
 (0)