[bugfix] fix service worker opaqueredirect error and ensure SW controls page before mount (#6275)

Fixes service worker network error by handling opaqueredirect responses
correctly and ensures SW registration completes before app mount to
prevent race conditions on first load.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6275-bugfix-fix-service-worker-opaqueredirect-error-and-ensure-SW-controls-page-before-mount-2976d73d36508106bc65dc82cdc62779)
by [Unito](https://www.unito.io)
This commit is contained in:
Christian Byrne
2025-10-24 22:30:16 -07:00
committed by GitHub
parent bab47869c9
commit 936da14dbc
4 changed files with 24 additions and 10 deletions

View File

@@ -67,15 +67,28 @@ self.addEventListener('fetch', (event) => {
})
)
// If redirected to external storage (GCS), follow without auth headers
// The signed URL contains its own authentication in query params
if (
response.type === 'opaqueredirect' ||
response.status === 302 ||
response.status === 301
) {
// Handle redirects to external storage (e.g., GCS signed URLs)
if (response.type === 'opaqueredirect') {
// Opaqueredirect: redirect occurred but response is opaque (headers not accessible)
// Re-fetch the original /api/view URL with redirect: 'follow'
// Browser will:
// 1. Send auth headers to /api/view (same-origin)
// 2. Receive 302 redirect to GCS
// 3. Automatically strip auth headers when following cross-origin redirect
// 4. Use GCS signed URL authentication instead
return fetch(event.request.url, {
method: 'GET',
headers: headers,
redirect: 'follow'
})
}
// Non-opaque redirect (status visible) - shouldn't normally happen with redirect: 'manual'
// but handle as fallback
if (response.status === 302 || response.status === 301) {
const location = response.headers.get('location')
if (location) {
// Follow redirect manually - do NOT include auth headers for external URLs
return fetch(location, {
method: 'GET',
redirect: 'follow'

View File

@@ -83,8 +83,9 @@ app
})
// Register auth service worker after Pinia is initialized (cloud-only)
// Wait for registration to complete before mounting to ensure SW controls the page
if (isCloud) {
void import('@/platform/auth/serviceWorker')
await import('@/platform/auth/serviceWorker')
}
app.mount('#vue-app')

View File

@@ -5,5 +5,5 @@ import { isCloud } from '@/platform/distribution/types'
* Tree-shaken for desktop/localhost builds via compile-time constant.
*/
if (isCloud) {
void import('./register')
await import('./register')
}

View File

@@ -54,4 +54,4 @@ function setupCacheInvalidation(): void {
})
}
void registerAuthServiceWorker()
await registerAuthServiceWorker()