Files
2026-05-27 23:47:53 +01:00

3.5 KiB

cross-origin — multi-origin Service Worker registration

Purpose

registerCrossOriginPackedResourceServiceWorker lets an application register a packed-resource Service Worker hosted on a different origin (typically a CDN subdomain). Before any browser request is dispatched the helper validates the SW URL's origin against a caller-supplied allowlist, so attacker-controlled or misconfigured CDN origins cannot slip past. On success the helper returns both the new registration and the container's current registration list so multi-tenant apps can confirm the CDN-origin SW is actually controlling the page.

Features

  • Strict allowlist validation BEFORE register() fires
  • Parses swUrl via the URL constructor — malformed URLs reject with PACKER_BROWSER.UNAUTHORIZED_ORIGIN
  • Delegates to registerPackedResourceServiceWorker so all the underlying contract (AbortSignal, error wrapping, message resolution) remains intact
  • Returns the full registration list (parity with clients.matchAll({ includeUncontrolled: true }))

Usage: Basic

import { registerCrossOriginPackedResourceServiceWorker } from "@suaveplan/packer-browser/utils";

await registerCrossOriginPackedResourceServiceWorker({
    swUrl: "https://cdn.example.com/sw.js",
    scope: "/packed/",
    allowedOrigins: ["https://cdn.example.com"],
});

Usage: Advanced

import {
    PACKER_BROWSER_CODES,
    PackerBrowserError,
    registerCrossOriginPackedResourceServiceWorker,
} from "@suaveplan/packer-browser";

try {
    const { registration, registrations } =
        await registerCrossOriginPackedResourceServiceWorker({
            swUrl: "https://cdn.example.com/sw.js",
            scope: "/",
            allowedOrigins: [
                "https://cdn.example.com",
                "https://cdn-fallback.example.com",
            ],
            container: navigator.serviceWorker,
            signal: shutdownController.signal,
        });
    console.log("registered", registration.scope, "of", registrations.length);
} catch (err) {
    if (
        err instanceof PackerBrowserError &&
        err.code === PACKER_BROWSER_CODES.UNAUTHORIZED_ORIGIN
    ) {
        console.warn("Origin not allowed; falling back to first-party SW.");
    }
}

API Reference

  • registerCrossOriginPackedResourceServiceWorker(opts: RegisterCrossOriginOptions): Promise<RegisterCrossOriginResult>
    • opts.swUrl: string — absolute SW URL. Required.
    • opts.scope: string — registration scope. Required.
    • opts.allowedOrigins: ReadonlyArray<string> — exact-string match. Required.
    • opts.container? — injectable container. Default: navigator.serviceWorker.
    • opts.messageResolver? — i18n resolver.
    • opts.signal? — AbortSignal forwarded to register().
    • Returns { registration, registrations }.

Implementation Notes

  • Origin equality is exact-string — there is no host-suffix matching. Allowlisting both https://cdn.example.com and https://cdn-fallback.example.com is explicit by design.
  • Malformed swUrl strings (relative paths, plain identifiers) yield UNAUTHORIZED_ORIGIN, not SW_REGISTRATION_FAILED, because the helper deliberately rejects before consulting the container.
  • The registrations list is the full container.getRegistrations() return value when a container is supplied; without one (e.g. in a Node smoke harness) the underlying register() already rejects with SW_REGISTRATION_FAILED so the caller never sees a partial list.