Skip to content

Commit

Permalink
feat: support IPFS/IPNS paths, Gateways, etc (#4)
Browse files Browse the repository at this point in the history
* feat: support IPFS/IPNS paths, Gateways, etc

Adds support for fetching resources in the form:

- IPFS Path, e.g. `/ipfs/<CID>`
- IPNS Path, e.g. `/ipns/<PeerId>`
- IPFS Gateway Path, e.g. `http://example.com/ipfs/<CID>`
- IPNS Gateway Path, e.g. `http://example.com/ipns/<PeerId>`
- IPFS Subdomain Gateway Path, e.g. `http://<CID>.ipfs.example.com`
- IPNS Subdomain Gateway Path, e.g. `http://<PeerId>.ipns.example.com`

* chore: simplify regex and test https urls too

* chore: apply suggestions from code review

Co-authored-by: Daniel Norman <[email protected]>

* chore: fix tests

* chore: more tests

* chore: remove $

* chore: https? test group name

---------

Co-authored-by: Daniel Norman <[email protected]>
Co-authored-by: Russell Dempsey <[email protected]>
  • Loading branch information
3 people authored Mar 3, 2024
1 parent 76485a4 commit e7f1816
Show file tree
Hide file tree
Showing 2 changed files with 625 additions and 147 deletions.
25 changes: 17 additions & 8 deletions packages/verified-fetch/src/utils/parse-url-string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,22 @@ export interface ParsedUrlStringResults {
query: ParsedUrlQuery
}

const URL_REGEX = /^(?<protocol>ip[fn]s):\/\/(?<cidOrPeerIdOrDnsLink>[^/$?]+)\/?(?<path>[^$?]*)\??(?<queryString>.*)$/
const URL_REGEX = /^(?<protocol>ip[fn]s):\/\/(?<cidOrPeerIdOrDnsLink>[^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/
const PATH_REGEX = /^\/(?<protocol>ip[fn]s)\/(?<cidOrPeerIdOrDnsLink>[^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/
const PATH_GATEWAY_REGEX = /^https?:\/\/(.*[^/])\/(?<protocol>ip[fn]s)\/(?<cidOrPeerIdOrDnsLink>[^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/
const SUBDOMAIN_GATEWAY_REGEX = /^https?:\/\/(?<cidOrPeerIdOrDnsLink>[^/.?]+)\.(?<protocol>ip[fn]s)\.([^/?]+)\/?(?<path>[^?]*)\??(?<queryString>.*)$/

function matchURLString (urlString: string): Record<string, string> {
for (const pattern of [URL_REGEX, PATH_REGEX, PATH_GATEWAY_REGEX, SUBDOMAIN_GATEWAY_REGEX]) {
const match = urlString.match(pattern)

if (match?.groups != null) {
return match.groups
}
}

throw new TypeError(`Invalid URL: ${urlString}, please use ipfs://, ipns://, or gateway URLs only`)
}

/**
* A function that parses ipfs:// and ipns:// URLs, returning an object with easily recognizable properties.
Expand All @@ -41,13 +56,7 @@ const URL_REGEX = /^(?<protocol>ip[fn]s):\/\/(?<cidOrPeerIdOrDnsLink>[^/$?]+)\/?
*/
export async function parseUrlString ({ urlString, ipns, logger }: ParseUrlStringInput, options?: ParseUrlStringOptions): Promise<ParsedUrlStringResults> {
const log = logger.forComponent('helia:verified-fetch:parse-url-string')
const match = urlString.match(URL_REGEX)

if (match == null || match.groups == null) {
throw new TypeError(`Invalid URL: ${urlString}, please use ipfs:// or ipns:// URLs only.`)
}

const { protocol, cidOrPeerIdOrDnsLink, path: urlPath, queryString } = match.groups
const { protocol, cidOrPeerIdOrDnsLink, path: urlPath, queryString } = matchURLString(urlString)

let cid: CID | undefined
let resolvedPath: string | undefined
Expand Down
Loading

0 comments on commit e7f1816

Please sign in to comment.