Skip to main content
Scramjet employs a sophisticated rewriting system to transparently proxy web content. The rewriters modify JavaScript, HTML, and CSS to intercept and redirect network requests, DOM operations, and URL references through the proxy.

JavaScript rewriting

The JavaScript rewriter is the most complex component, powered by a Rust-based WASM module using the OXC parser for high-performance AST transformations.

Architecture

JavaScript rewriting occurs in two layers:
  1. TypeScript wrapper (src/shared/rewriters/js.ts) - Handles error recovery and sourcemap injection
  2. Rust/WASM core (rewriter/js/) - Performs AST-level transformations using OXC

Rewriter output

The WASM rewriter returns structured output:
The rewriter can process both strings and Uint8Array for efficiency. When working with large scripts, use Uint8Array to avoid encoding overhead.

Error handling

Scramjet includes graceful error recovery:
The allowInvalidJs flag should only be enabled for debugging. It bypasses rewriting for malformed JavaScript, which can break proxy functionality.

URL transformations in JavaScript

The rewriter intercepts:
  • Function calls: fetch(), XMLHttpRequest.open(), WebSocket()
  • Property access: location.href, document.URL
  • Dynamic imports: import(), require()
  • Worker creation: new Worker(), new SharedWorker()

HTML rewriting

The HTML rewriter uses htmlparser2 for streaming DOM parsing and dom-serializer for output generation.

Implementation

HTML rules

Scramjet maintains a set of HTML rewriting rules that define which attributes to rewrite:

Script injection

When fromTop=true, Scramjet injects client scripts into the <head>:
Inline event handlers: Event attributes like onclick are rewritten as JavaScript:
Import maps: JSON import maps have URLs rewritten:
CSP meta tags: Content Security Policy tags are commented out:

Srcset rewriting

Responsive images with srcset attributes require special handling:

CSS rewriting

The CSS rewriter targets URL references in stylesheets using regex-based transformations.

Basic usage

CSS URL patterns

The rewriter handles:
  1. url() function: url('/path/to/resource')
  2. @import rules: @import url('...') or @import '...'
CSS rewriting is less complex than JavaScript because CSS doesn’t contain executable code that can dynamically generate URLs.

URL metadata (URLMeta)

All rewriters share a common URLMeta type that provides context:

Base URL handling

The <base> tag affects relative URL resolution:
Scramjet updates meta.base when encountering <base> tags:

Performance considerations

WASM rewriter pooling

Scramjet maintains a pool of rewriter instances to avoid initialization overhead:

Timing and profiling

Enable rewriter logs to track performance:

Common patterns

Rewriting downloaded resources

Handling special URLs

Some URLs require special treatment: