Skip to content

Commit fd86e6a

Browse files
authored
fix: append query path to path resolved from IPNS name (#3)
If an IPNS name resolves to a CID+path, and the requested URL also has a path, the resolved path should be the path from the IPNS record joined with the path from the requested URL, not the other way round.
1 parent b9b959b commit fd86e6a

File tree

4 files changed

+406
-341
lines changed

4 files changed

+406
-341
lines changed

packages/verified-fetch/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
"@helia/json": "^3.0.1",
9191
"@helia/utils": "^0.0.2",
9292
"@ipld/car": "^5.3.0",
93+
"@libp2p/interface-compliance-tests": "^5.3.2",
9394
"@libp2p/logger": "^4.0.7",
9495
"@libp2p/peer-id-factory": "^4.0.7",
9596
"@sgtpooki/file-type": "^1.0.1",

packages/verified-fetch/src/utils/parse-url-string.ts

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,19 @@ export async function parseUrlString ({ urlString, ipns, logger }: ParseUrlStrin
9898
resolvedPath = resolveResult?.path
9999
log.trace('resolved %s to %c', cidOrPeerIdOrDnsLink, cid)
100100
ipnsCache.set(cidOrPeerIdOrDnsLink, resolveResult, 60 * 1000 * 2)
101-
} catch (err) {
101+
} catch (err: any) {
102102
log.error('Could not resolve DnsLink for "%s"', cidOrPeerIdOrDnsLink, err)
103-
errors.push(err as Error)
103+
errors.push(err)
104104
}
105105
}
106106
}
107107
}
108108

109109
if (cid == null) {
110+
if (errors.length === 1) {
111+
throw errors[0]
112+
}
113+
110114
throw new AggregateError(errors, `Invalid resource. Cannot determine CID from URL "${urlString}"`)
111115
}
112116

@@ -129,26 +133,37 @@ export async function parseUrlString ({ urlString, ipns, logger }: ParseUrlStrin
129133
}
130134
}
131135

132-
/**
133-
* join the path from resolve result & given path.
134-
* e.g. /ipns/<peerId>/ that is resolved to /ipfs/<cid>/<path1>, when requested as /ipns/<peerId>/<path2>, should be
135-
* resolved to /ipfs/<cid>/<path1>/<path2>
136-
*/
137-
const pathParts = []
136+
return {
137+
protocol,
138+
cid,
139+
path: joinPaths(resolvedPath, urlPath),
140+
query
141+
}
142+
}
138143

139-
if (urlPath.length > 0) {
140-
pathParts.push(urlPath)
144+
/**
145+
* join the path from resolve result & given path.
146+
* e.g. /ipns/<peerId>/ that is resolved to /ipfs/<cid>/<path1>, when requested as /ipns/<peerId>/<path2>, should be
147+
* resolved to /ipfs/<cid>/<path1>/<path2>
148+
*/
149+
function joinPaths (resolvedPath: string | undefined, urlPath: string): string {
150+
let path = ''
151+
152+
if (resolvedPath != null) {
153+
path += resolvedPath
141154
}
142155

143-
if (resolvedPath != null && resolvedPath.length > 0) {
144-
pathParts.push(resolvedPath)
156+
if (urlPath.length > 0) {
157+
path = `${path.length > 0 ? `${path}/` : path}${urlPath}`
145158
}
146-
const path = pathParts.join('/')
147159

148-
return {
149-
protocol,
150-
cid,
151-
path,
152-
query
160+
// replace duplicate forward slashes
161+
path = path.replace(/\/(\/)+/g, '/')
162+
163+
// strip trailing forward slash if present
164+
if (path.startsWith('/')) {
165+
path = path.substring(1)
153166
}
167+
168+
return path
154169
}

0 commit comments

Comments
 (0)