Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle helia-sw query from _redirects #67

Merged
merged 5 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 2 additions & 13 deletions src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
import React, { useContext, useEffect } from 'react'
import React, { useContext } from 'react'
import Config from './components/config.tsx'
import { ConfigContext } from './context/config-context.tsx'
import HelperUi from './helper-ui.tsx'
import { isConfigPage } from './lib/is-config-page.ts'
import { isPathOrSubdomainRequest, findOriginIsolationRedirect } from './lib/path-or-subdomain.ts'
import { isPathOrSubdomainRequest } from './lib/path-or-subdomain.ts'
import RedirectPage from './redirectPage.tsx'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved to service-worker-context


function App (): JSX.Element {
const { isConfigExpanded, setConfigExpanded } = useContext(ConfigContext)

useEffect(() => {
async function originEnforcement (): Promise<void> {
// enforce early when loaded before SW was registered
const originRedirect = await findOriginIsolationRedirect(window.location)
if (originRedirect !== null) {
window.location.replace(originRedirect)
}
}
void originEnforcement()
}, [])

if (isConfigPage()) {
setConfigExpanded(true)
return <Config />
Expand Down
42 changes: 41 additions & 1 deletion src/context/service-worker-context.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
/**
* @file This file contains the ServiceWorkerProvider component which is used to register the service worker,
* and provide the isServiceWorkerRegistered state to the rest of the app.
*
* URL / location logic dependent upon the service worker being registered should be handled here. Some examples of this are:
*
* Before the Service Worker is registered (e.g. first requests to root hosted domain or subdomains):
*
* 1. Being redirected from _redirects file to a ?helia-sw= url
* 2. The app is loaded because service worker is not yet registered, we need to reload the page so the service worker intercepts the request
*
* After the service worker is loaded. Usually any react code isn't loaded, but some edge cases are:
* 1. The page being loaded using some /ip[fn]s/<path> url, but subdomain isolation is supported, so we need to redirect to the isolated origin
*/
Comment on lines +1 to +14
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some explanations

import React, { createContext, useEffect, useState } from 'react'
import { translateIpfsRedirectUrl } from '../lib/ipfs-hosted-redirect-utils.ts'
import { error } from '../lib/logger.ts'
import { findOriginIsolationRedirect } from '../lib/path-or-subdomain.ts'
import { registerServiceWorker } from '../service-worker-utils.ts'

export const ServiceWorkerContext = createContext({
Expand All @@ -9,8 +25,32 @@ export const ServiceWorkerContext = createContext({
export const ServiceWorkerProvider = ({ children }): JSX.Element => {
const [isServiceWorkerRegistered, setIsServiceWorkerRegistered] = useState(false)

const windowLocation = translateIpfsRedirectUrl(window.location.href)

useEffect(() => {
if (isServiceWorkerRegistered) {
/**
* The service worker is registered, now we need to check for "helia-sw" and origin isolation support
*/
if (windowLocation.href !== window.location.href) {
/**
* We're at a domain with ?helia-sw=, we can reload the page so the service worker will
* capture the request
*/
window.location.replace(windowLocation.href)
Comment on lines +35 to +40
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this check could be more explicit for future devs, but translateIpfsRedirectUrl should make understanding this easy.

} else {
/**
* ?helia-sw= url handling is done, now we can check for origin isolation redirects
*/
void findOriginIsolationRedirect(windowLocation).then((originRedirect) => {
if (originRedirect !== null) {
window.location.replace(originRedirect)
}
})
Comment on lines +45 to +49
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/?helia-sw= redirect will load path URL.. if not handled by service worker for whatever reason (it should be, 99.99% of the time) then this will redirect that path request to subdomain if supported.

}
/**
* The service worker is registered, we don't need to do any more work
*/
return
}
async function doWork (): Promise<void> {
Expand All @@ -32,7 +72,7 @@ export const ServiceWorkerProvider = ({ children }): JSX.Element => {
}
}
void doWork()
}, [])
}, [isServiceWorkerRegistered])
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're dependent upon isServiceWorkerRegistered, so we need to execute this effect more than a single time now


return (
<ServiceWorkerContext.Provider value={{ isServiceWorkerRegistered }}>
Expand Down
15 changes: 15 additions & 0 deletions src/lib/ipfs-hosted-redirect-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* If you host helia-service-worker-gateway on an IPFS domain, the redirects file will route some requests from
* `<domain>/<wildcard-splat>` to `https://<domain>/?helia-sw=<wildcard-splat>`.
*
* This function will check for "?helia-sw=" in the URL and modify the URL so that it works with the rest of our logic
*/
export function translateIpfsRedirectUrl (urlString: string): URL {
const url = new URL(urlString)
const heliaSw = url.searchParams.get('helia-sw')
if (heliaSw != null) {
url.searchParams.delete('helia-sw')
url.pathname = heliaSw
}
return url
}
Loading