Skip to main content
The ScramjetServiceWorker class handles request interception in the service worker context. It routes proxy requests, manages configuration, and handles the core logic for proxying.

Constructor

Creates a new ScramjetServiceWorker instance.
new ScramjetServiceWorker()

Example

const { ScramjetServiceWorker } = $scramjetLoadWorker();

const scramjet = new ScramjetServiceWorker();

self.addEventListener("fetch", async (ev) => {
  await scramjet.loadConfig();

  if (scramjet.route(ev)) {
    ev.respondWith(scramjet.fetch(ev));
  }
});

Properties

client

BareClient instance to fetch requests under a chosen proxy transport.
client: BareClient

config

Current ScramjetConfig saved in memory.
config: ScramjetConfig

cookieStore

Scramjet’s cookie jar for cookie emulation through other storage means.
cookieStore: CookieStore

serviceWorkers

Fake service worker registrations for sites that require service worker support.
serviceWorkers: FakeServiceWorker[]
This will eventually be replaced with a NestedSW feature under a flag, but will remain for stability.

syncPool

Recorded sync messages in the message queue.
syncPool: Record<number, (val?: any) => void>

synctoken

Current sync token for collected messages in the queue.
synctoken: number

Methods

loadConfig()

Persists the current Scramjet config from IndexedDB into memory.
async loadConfig(): Promise<void>
You must call loadConfig() before using route() or fetch() to ensure the configuration is loaded.

Example

self.addEventListener("fetch", async (ev) => {
  await scramjet.loadConfig();

  if (scramjet.route(ev)) {
    ev.respondWith(scramjet.fetch(ev));
  }
});
The Scramjet config can be dynamically updated via the ScramjetController APIs, which is why it needs to be loaded from IndexedDB.

route()

Determines whether to route a request from a FetchEvent in Scramjet.
route({ request }: FetchEvent): boolean
request
Request
required
The fetch request from the FetchEvent

Returns

true if the request should be handled by Scramjet, false otherwise.

Example

self.addEventListener("fetch", async (ev) => {
  await scramjet.loadConfig();

  if (scramjet.route(ev)) {
    ev.respondWith(scramjet.fetch(ev));
  }
});

fetch()

Handles a FetchEvent to be routed in Scramjet. This is the heart of adding Scramjet support to your web proxy.
async fetch({ request, clientId }: FetchEvent): Promise<Response>
request
Request
required
The fetch request from the FetchEvent
clientId
string
required
The client ID from the FetchEvent

Returns

A Promise that resolves to the proxied Response.

Example

self.addEventListener("fetch", async (ev) => {
  await scramjet.loadConfig();

  if (scramjet.route(ev)) {
    ev.respondWith(scramjet.fetch(ev));
  }
});

dispatch()

Dispatches a message in the message queues.
async dispatch(client: Client, data: MessageW2C): Promise<MessageC2W>
client
Client
required
The client to send the message to
data
MessageW2C
required
The message data to send

Returns

A Promise that resolves to the response message from the client.
This method is used internally for communication between the service worker and clients.

Message types

The service worker communicates with clients using typed messages.

MessageC2W

Message types sent from the client to the service worker.
type MessageC2W = MessageCommon & (
  | RegisterServiceWorkerMessage
  | CookieMessage
  | ConfigMessage
);

type MessageCommon = {
  scramjet$token?: number;
};

MessageW2C

Message types sent from the service worker to the client.
type MessageW2C = MessageCommon & (
  | CookieMessage
  | DownloadMessage
);

RegisterServiceWorkerMessage

type RegisterServiceWorkerMessage = {
  scramjet$type: "registerServiceWorker";
  port: MessagePort;
  origin: string;
};

CookieMessage

type CookieMessage = {
  scramjet$type: "cookie";
  cookie: string;
  url: string;
};

ConfigMessage

type ConfigMessage = {
  scramjet$type: "loadConfig";
  config: ScramjetConfig;
};

DownloadMessage

type DownloadMessage = {
  scramjet$type: "download";
  download: ScramjetDownload;
};

Complete example

// service-worker.js
const { ScramjetServiceWorker } = $scramjetLoadWorker();

const scramjet = new ScramjetServiceWorker();

self.addEventListener("fetch", async (event) => {
  // Load config from IndexedDB
  await scramjet.loadConfig();

  // Check if this request should be handled by Scramjet
  if (scramjet.route(event)) {
    // Handle the request through Scramjet
    event.respondWith(scramjet.fetch(event));
  }
});

Build docs developers (and LLMs) love