Skip to main content
The ScramjetServiceWorker is the core component that intercepts all network requests and proxies them through the configured transport. This page explains how it works.

Overview

Service Workers provide a programmable network proxy that runs in the browser. Scramjet leverages this to intercept fetch requests, decode URLs, fetch content, rewrite it, and return the modified response.
Service Workers run in a separate context from your web pages. They persist across page loads and can intercept requests from multiple clients (tabs/windows).

Class structure

The ScramjetServiceWorker class is defined in src/worker/index.ts:

Initialization

When the Service Worker starts, it creates a ScramjetServiceWorker instance:
The constructor initializes:
  1. BareClient for transport
  2. CookieStore for cookie emulation
  3. Message listeners for client communication
  4. IndexedDB to load saved cookies

Loading configuration

The Service Worker loads its configuration from IndexedDB:
This is called automatically by scramjet.fetch() if the config hasn’t been loaded yet. The config contains:
  • URL prefix for routing
  • Feature flags
  • Codec functions for URL encoding/decoding
  • File paths for injected scripts
Configuration can be dynamically updated at runtime via messages from the controller. Changes are persisted to IndexedDB.

Request routing

The route() method determines if a request should be handled by Scramjet:
Requests are routed if they:
  • Start with the configured prefix (e.g., /scramjet/)
  • Request the WASM rewriter file

Request handling

The fetch() method orchestrates the entire proxy flow:
The actual logic is in handleFetch() from src/worker/fetch.ts.

Fetch flow

1

Parse query parameters

Extract metadata from the URL’s query string:
2

Decode URL

Convert the proxied URL back to the real destination:
3

Build metadata context

Create the URLMeta object for rewriters:
4

Handle special URLs

Blob and data URLs are handled directly:
5

Process request headers

Rewrite headers for the real request:
6

Dispatch request event

Allow external code to modify the request:
7

Fetch via transport

Use BareClient to make the actual request:
8

Process response

Rewrite headers, handle cookies, and rewrite the body based on content type.

Response handling

The handleResponse() function processes the fetched response:

Header rewriting

This:
  • Rewrites Location headers for redirects
  • Processes Set-Cookie headers
  • Removes Permissions-Policy headers that might block Scramjet features
  • Handles CORS headers

Body rewriting

Based on the request destination, the response body is rewritten:
HTML rewriting injects Scramjet’s client scripts into the <head> and rewrites:
  • URL attributes (src, href, action, etc.)
  • Inline <script> and <style> tags
  • Event handler attributes (onclick, etc.)
  • Import maps
  • <base> tags
  • Meta refresh tags
  • CSP meta tags (removed)
JavaScript is rewritten using an oxc-based WASM rewriter that:
  • Wraps function calls to intercept APIs
  • Rewrites property accesses
  • Injects runtime helpers
  • Generates source maps for debugging
  • Handles both classic scripts and ES modules

Download interception

When the interceptDownloads flag is enabled, Scramjet can intercept file downloads:

Message passing

The Service Worker communicates with clients via postMessage:

Receiving messages

Dispatching messages

The dispatch() method sends messages and waits for responses:
Scramjet emulates cookies using the CookieStore class because:
  1. Service Workers cannot access document.cookie
  2. Real cookies would leak the proxy origin
  3. Cookie attributes (domain, path, etc.) need special handling
Cookies are:
  • Stored in the Service Worker’s CookieStore instance
  • Persisted to IndexedDB
  • Synced to clients via postMessage
  • Added to outgoing requests via the Cookie header

Events

The Service Worker dispatches custom events:

ScramjetRequestEvent

Fired before making a request, allowing modification:

ScramjetHandleResponseEvent

Fired after receiving a response:

Best practices

Never modify the Service Worker config directly. Always use the controller’s modifyConfig() method to ensure changes are persisted.
Use the request event to add custom headers or authentication to proxied requests.

Next steps

URL rewriting

Learn how URLs are encoded, decoded, and rewritten

Configuration

Explore Service Worker configuration options