From 5020d3b0483760411a10166b320f0467ae4917c1 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Thu, 29 Sep 2022 01:47:20 +0200 Subject: [PATCH 1/3] feat: /how-to/detect-ipfs-on-web This adds a page with some best practices around detecting IPFS resources on the web, based on recent discussions with Brave team and our effort to streamline implmenetation there. --- docs/.vuepress/config.js | 23 +++++- docs/how-to/detect-ipfs-on-web.md | 128 ++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 docs/how-to/detect-ipfs-on-web.md diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index f0122066f..0446bc2a8 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -248,7 +248,8 @@ module.exports = { collapsable: true, children: [ '/how-to/address-ipfs-on-web', - '/how-to/browser-tools-frameworks' + '/how-to/browser-tools-frameworks', + 'how-to/detect-ipfs-on-web', ] }, { @@ -512,7 +513,25 @@ module.exports = { ], 'vuepress-plugin-chunkload-redirect', 'vuepress-plugin-ipfs', - 'vuepress-plugin-mermaidjs', + [ + 'vuepress-plugin-mermaidjs', + { + securityLevel: 'loose', // safe as we dont allow mermaid in user content. allows for additional interactivity + theme: 'base', + themeVariables: { // values from 'IPFS brand sheet' at https://github.com/ipfs/ipfs-gui#resources + primaryColor: '#D7EDF1', + edgeLabelBackground:'#edf0f4', + tertiaryColor: '#edf0f4' + }, + deterministicIds: true, + deterministicIDSeed: DEPLOY_DOMAIN, + flowchart: { + htmlLabels: true, + curve: 'basis', + useMaxWidth: false + } + } + ], 'tabs' ], extraWatchFiles: ['.vuepress/nav/en.js'] diff --git a/docs/how-to/detect-ipfs-on-web.md b/docs/how-to/detect-ipfs-on-web.md new file mode 100644 index 000000000..87aaf55aa --- /dev/null +++ b/docs/how-to/detect-ipfs-on-web.md @@ -0,0 +1,128 @@ +--- +title: Discover IPFS content from Web2 +description: Learn how to add support for content-addressed IPFS resources in web browsers and other user agents. +--- + +# Discover IPFS content from Web2 + +The goal of this page is to provide some suggestions and best practices for Web 2 web browsers and other [user agents](https://en.wikipedia.org/wiki/User_agent) that are interested in adding support for [content-addressed resources](/how-to/address-ipfs-on-web). + +## Detecting content-addressed resources + +In many cases, IPFS resources can be detected just by looking at the URI, especially if it is an HTTP URL pointed at a public gateway. This allows a browser to upgrade the transport protocol to IPFS, and removes the need to send an HTTP request to a remote server. + +### Methodology + +To determine if a resource is an IPFS resource, answer the following questions in order: + +1. Does the `URL` follow [path or subdomain gateway](/how-to/address-ipfs-on-web/) convention? +1. If not, does [DNSLink](/concepts/dnslink/) with an IPFS path exist for `URL.hostname`? + +If you answered yes to either of the above questions, a user agent should be able to find a content path that can be used for data retrieval over IPFS, as described in the illustration below: + +```mermaid +flowchart TD + Start[Top-level navigation event] + IsGateway{Is it a Gateway URL?
foo.tld/ipxs/id/..
id.ipxs.foo.com/..} + + Start -->|new URL in address bar| IsGateway + IsGateway ==>|YES| IsPathOrSubdomain + IsPathOrSubdomain -->|Path Gateway| ExtractFromPath + IsPathOrSubdomain -->|Subdomain Gateway| ExtractFromSubdomain + + subgraph GwURLToPath [Convert Gateway URL to a Content Path] + IsPathOrSubdomain{Is the Gateway URL 'path'
or 'subdomain' based?} + ExtractFromPath[Extract
URL.pathname] + ExtractFromSubdomain[Read namespace
and
identifier from
URL.hostname and
prepend to URL.pathname.
E.g., turn
id.ipxs.foo.com/pathname
into /ipxs/id/pathname] + end + + PotentialContentPath[Found a Potential Content Path] + + ExtractFromPath --> PotentialContentPath + ExtractFromSubdomain --> PotentialContentPath + PotentialContentPath -->|/ipxs/id/sub/path..| IsIpfsOrIpns + + subgraph PathValidation [Is the Content Path valid?] + IsIpfsOrIpns{Is it /ipfs/
or /ipns/
?} + ValidateRootCID{Is id
a valid CID?} + ValidateIPNSKey{Is id
a valid CID
with libp2p-key
codec?} + ValidateDNSLink{Is id
a DNSLink name
with TXT record:
dnslink=/ipfs/
or =/ipns/} + + IsIpfsOrIpns --->|/ipfs/id/..| ValidateRootCID + IsIpfsOrIpns -->|/ipns/id/..| ValidateIPNSKey + ValidateIPNSKey -->|NO| ValidateDNSLink + end + + subgraph FoundValidIPFSContent [Confirmed we've found a Valid IPFS Resource] + style FoundValidIPFSContent margin-top: 50 + ValidIPFSCID[Valid /ipfs/cid/..
Content Path] + ValidIPNSKey[Valid /ipns/key/..
Content Path] + ValidDNSLink[Valid /ipns/dnslink/..
Content Path] + + ValidateRootCID ===>|YES, /ipfs/cid/..| ValidIPFSCID + ValidateIPNSKey ===>|YES, /ipns/key/..| ValidIPNSKey + ValidateDNSLink ===>|YES, /ipfs/dnslink/..| ValidDNSLink + end + + subgraph NonGwURLToPath [See if non-Gateway URL has a Content Path] + IsCachedDNSLink{Does
URL.hostname
match a cached
DNSLink name?} + IsHeaderPresent{Is X-Ipfs-Path
header present?} + IsError{Did request fail?
HTTP error>500
or network error} + IsDNSLinkAtHostname{Does DNSLink exists
for URL.hostname?
} + PathFromHeader[Read value from X-Ipfs-Path] + end + + IsGateway -->|NO| IsCachedDNSLink + IsCachedDNSLink ==>|YES| ValidDNSLink + IsCachedDNSLink -->|NO| IsHeaderPresent + IsHeaderPresent ==>|YES| IsDNSLinkAtHostname + IsHeaderPresent -->|NO| IsError + IsError ==>|YES| IsDNSLinkAtHostname + IsDNSLinkAtHostname ==>|YES| ValidDNSLink + IsDNSLinkAtHostname -->|NO| PathFromHeader + PathFromHeader --> PotentialContentPath +``` + +## What to do with detected paths + +What you do with the detected IPFS resource path depends on the type of path. + +### Immutable `/ipfs/cid/..` + +- Display "Open via IPFS" button in UI + - Clicking it should open `ipfs://cid/path?query#hash` (preserving any `?query` or `#hash` from the original HTTP URL) +- If "IPFS Gateway Redirect / Protocol Upgrade" feature is enabled, and the HTTP URL was a gateway one, redirect automatically to `ipfs://cid/path?query#hash` + +### Mutable `/ipns/key/..` +- Display "Open via IPFS" button in UI + - Clicking it should open `ipns://key/path?query#hash` (preserving any `?query` or `#hash` from the original HTTP URL) +- If "IPFS Gateway Redirect / Protocol Upgrade" is enabled, and the original HTTP URL was a gateway one, redirect automatically to `ipns://dnslink/path?query#hash` + +### Mutable `/ipns/dnslink/..` + +- Display "Open via IPFS" button in UI + - Clicking it should open `ipns://dnslink/path?query#hash` (preserving `?query` or `#hash` from the original HTTP URL) +- If "DNSLink Website Redirect / Protocol Upgrade" is enabled, redirect automatically to `ipns://dnslink/path?query#hash` +- It is a good practice to internally cache the fact that domain has a valid DNSLink. + - TTL from TXT record can be used as a hint when to expire cache entry. + - Performance can be improved further by using cached flag and revalidating it asynchronously, without blocking browser navigation. + +## FAQ + +**What if a browser does not support `ipfs://` and `ipns://` natively?** Implementations can use an [HTTP Gateway](/reference/http/gateway/) as a fallback, convert ththe path to `//gatewayhost/ipxs/id/..`-type paths, or leverage the built-in URI router at `//gatewayhost/ipfs/?uri=%s` + +**Why should `?query` or `#hash` from the original HTTP URL be preserved?** The link could point at specific `#section` of a longer article. It is also common for JavaScript running on a page to use the `?query` and `#hash` for navigation and ad-hoc storage of some state. + +**Should a user agent redirect when the URL does not match gateway convention, `URL.hostname` does not have a valid DNSLink, but `X-Ipfs-Path` is present in HTTP response AND points at an immutable `/ipfs/cid`?** This is an edge case, and we've seen that it is often a misconfiguration caused by an invalid or missing DNSLink that could lead to bad UX when automatic redirect is involved. The user ends up on an immutable copy of a website, bookmarks it or keeps tabs open, and misses updates when DNSLink setup is fixed. It is suggested to not redirect this edge case, or provide a setting that controls this type of redirect. Usually, showing "Open via IPFS" in the user interface is enough for this case. + +## Implementation examples + +### Brave + +[Brave has supported IPFS since 2021](https://brave.com/brave-integrates-ipfs/). Current features include `ipfs://` and `ipns://` URI support, ability to resolve this type of address using a public / local gateway, opt-in Gateway and/or DNSLink redirects, and an **Open via IPFS** button in the address bar: + +> ![Open via IPFS in Brave address bar](https://user-images.githubusercontent.com/157609/110859368-9a0d7300-82bb-11eb-934d-4e38718dbacb.png) + +### IPFS Companion + +Firefox and Chromium-based browsers such as Google Chrome or Microsoft Edge can be augumented with [IPFS Companion](/install/ipfs-companion/) browser extension, which allows them to detect IPFS content. From 695389a920cf0691317ca43cf3c85bb08f7e1bc7 Mon Sep 17 00:00:00 2001 From: ElPaisano <113373882+ElPaisano@users.noreply.github.com> Date: Mon, 25 Sep 2023 16:58:24 -0600 Subject: [PATCH 2/3] Fixes --- docs/.vuepress/config.js | 2 +- docs/how-to/detect-ipfs-on-web.md | 27 +++++++++++++++------------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 0446bc2a8..1f51157ed 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -249,7 +249,7 @@ module.exports = { children: [ '/how-to/address-ipfs-on-web', '/how-to/browser-tools-frameworks', - 'how-to/detect-ipfs-on-web', + '/how-to/detect-ipfs-on-web', ] }, { diff --git a/docs/how-to/detect-ipfs-on-web.md b/docs/how-to/detect-ipfs-on-web.md index 87aaf55aa..8e55136bd 100644 --- a/docs/how-to/detect-ipfs-on-web.md +++ b/docs/how-to/detect-ipfs-on-web.md @@ -5,7 +5,7 @@ description: Learn how to add support for content-addressed IPFS resources in we # Discover IPFS content from Web2 -The goal of this page is to provide some suggestions and best practices for Web 2 web browsers and other [user agents](https://en.wikipedia.org/wiki/User_agent) that are interested in adding support for [content-addressed resources](/how-to/address-ipfs-on-web). +The goal of this page is to provide some suggestions and best practices for Web 2 web browsers and other [user agents](https://en.wikipedia.org/wiki/User_agent) that are interested in adding support for [content-addressed resources](./address-ipfs-on-web.md). ## Detecting content-addressed resources @@ -15,8 +15,8 @@ In many cases, IPFS resources can be detected just by looking at the URI, especi To determine if a resource is an IPFS resource, answer the following questions in order: -1. Does the `URL` follow [path or subdomain gateway](/how-to/address-ipfs-on-web/) convention? -1. If not, does [DNSLink](/concepts/dnslink/) with an IPFS path exist for `URL.hostname`? +1. Does the `URL` follow [path or subdomain gateway](./address-ipfs-on-web.md) convention? +1. If not, does [DNSLink](../concepts/dnslink.md) with an IPFS path exist for `URL.hostname`? If you answered yes to either of the above questions, a user agent should be able to find a content path that can be used for data retrieval over IPFS, as described in the illustration below: @@ -83,6 +83,8 @@ flowchart TD PathFromHeader --> PotentialContentPath ``` +
+ ## What to do with detected paths What you do with the detected IPFS resource path depends on the type of path. @@ -107,14 +109,6 @@ What you do with the detected IPFS resource path depends on the type of path. - TTL from TXT record can be used as a hint when to expire cache entry. - Performance can be improved further by using cached flag and revalidating it asynchronously, without blocking browser navigation. -## FAQ - -**What if a browser does not support `ipfs://` and `ipns://` natively?** Implementations can use an [HTTP Gateway](/reference/http/gateway/) as a fallback, convert ththe path to `//gatewayhost/ipxs/id/..`-type paths, or leverage the built-in URI router at `//gatewayhost/ipfs/?uri=%s` - -**Why should `?query` or `#hash` from the original HTTP URL be preserved?** The link could point at specific `#section` of a longer article. It is also common for JavaScript running on a page to use the `?query` and `#hash` for navigation and ad-hoc storage of some state. - -**Should a user agent redirect when the URL does not match gateway convention, `URL.hostname` does not have a valid DNSLink, but `X-Ipfs-Path` is present in HTTP response AND points at an immutable `/ipfs/cid`?** This is an edge case, and we've seen that it is often a misconfiguration caused by an invalid or missing DNSLink that could lead to bad UX when automatic redirect is involved. The user ends up on an immutable copy of a website, bookmarks it or keeps tabs open, and misses updates when DNSLink setup is fixed. It is suggested to not redirect this edge case, or provide a setting that controls this type of redirect. Usually, showing "Open via IPFS" in the user interface is enough for this case. - ## Implementation examples ### Brave @@ -125,4 +119,13 @@ What you do with the detected IPFS resource path depends on the type of path. ### IPFS Companion -Firefox and Chromium-based browsers such as Google Chrome or Microsoft Edge can be augumented with [IPFS Companion](/install/ipfs-companion/) browser extension, which allows them to detect IPFS content. +Firefox and Chromium-based browsers such as Google Chrome or Microsoft Edge can access IPFS with the [IPFS Companion](../install/ipfs-companion.md) browser extension, which allows them to detect IPFS content. + + +## FAQ + +**What if a browser does not support `ipfs://` and `ipns://` natively?** Implementations can use an [HTTP Gateway](../reference/http/gateway.md) as a fallback, convert ththe path to `//gatewayhost/ipxs/id/..`-type paths, or leverage the built-in URI router at `//gatewayhost/ipfs/?uri=%s` + +**Why should `?query` or `#hash` from the original HTTP URL be preserved?** The link could point at specific `#section` of a longer article. It is also common for JavaScript running on a page to use the `?query` and `#hash` for navigation and ad-hoc storage of some state. + +**Should a user agent redirect when the URL does not match gateway convention, `URL.hostname` does not have a valid DNSLink, but `X-Ipfs-Path` is present in HTTP response AND points at an immutable `/ipfs/cid`?** This is an edge case, and we've seen that it is often a misconfiguration caused by an invalid or missing DNSLink that could lead to bad UX when automatic redirect is involved. The user ends up on an immutable copy of a website, bookmarks it or keeps tabs open, and misses updates when DNSLink setup is fixed. It is suggested to not redirect this edge case, or provide a setting that controls this type of redirect. Usually, showing "Open via IPFS" in the user interface is enough for this case. From 75308dd97f6f6a73ea91072149bd9a15acff030d Mon Sep 17 00:00:00 2001 From: ElPaisano <113373882+ElPaisano@users.noreply.github.com> Date: Mon, 25 Sep 2023 17:00:12 -0600 Subject: [PATCH 3/3] typo --- docs/how-to/detect-ipfs-on-web.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to/detect-ipfs-on-web.md b/docs/how-to/detect-ipfs-on-web.md index 8e55136bd..310925fdb 100644 --- a/docs/how-to/detect-ipfs-on-web.md +++ b/docs/how-to/detect-ipfs-on-web.md @@ -124,7 +124,7 @@ Firefox and Chromium-based browsers such as Google Chrome or Microsoft Edge can ## FAQ -**What if a browser does not support `ipfs://` and `ipns://` natively?** Implementations can use an [HTTP Gateway](../reference/http/gateway.md) as a fallback, convert ththe path to `//gatewayhost/ipxs/id/..`-type paths, or leverage the built-in URI router at `//gatewayhost/ipfs/?uri=%s` +**What if a browser does not support `ipfs://` and `ipns://` natively?** Implementations can use an [HTTP Gateway](../reference/http/gateway.md) as a fallback, convert the path to `//gatewayhost/ipxs/id/..`-type paths, or leverage the built-in URI router at `//gatewayhost/ipfs/?uri=%s` **Why should `?query` or `#hash` from the original HTTP URL be preserved?** The link could point at specific `#section` of a longer article. It is also common for JavaScript running on a page to use the `?query` and `#hash` for navigation and ad-hoc storage of some state.