diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index f0122066f..1f51157ed 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..310925fdb --- /dev/null +++ b/docs/how-to/detect-ipfs-on-web.md @@ -0,0 +1,131 @@ +--- +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](./address-ipfs-on-web.md). + +## 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](./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: + +```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. + +## 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 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 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. + +**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.