HTTP and browser networking

On this page

  1. Proxy configuration and credentials
  2. Rewriting options
  3. Framing, streaming, and tunnels
  4. Browser-side compatibility remains separate
  5. Minimal integration checks
  6. Source references

All four current Outer Loop web views use the local HTTP frontend. Rewriting is enabled on macOS, iOS, and Linux; Windows disables it because WebView2 can send localhost requests through the proxy directly. It supports HTTP/1.1 proxy requests and CONNECT. SOCKS remains useful for raw network clients, but it does not perform HTTP compatibility rewriting.

Proxy configuration and credentials

Listeners bind to IPv4 loopback (127.0.0.1). Configure the web view before loading a page, use the actual port returned by start, and authenticate only to that local proxy endpoint.

HTTP uses Basic proxy authentication when configuration endpoint supplies credentials; both username and password must be nonempty, and the username cannot contain :. A NULL endpoint disables authentication. The frontend copies the supplied credentials and realm. HTTP does not generate them for the host.

SOCKS uses username/password authentication by default and can generate credentials. Explicit no-authentication is also available. Proxy credentials are distinct from SSH passwords and sudo passwords. They grant access to the frontend’s fixed session pool.

Use a browser’s proxy credential mechanism. Do not put proxy secrets into page URLs, JavaScript, or ordinary origin Authorization headers. Challenge handlers must distinguish a proxy challenge from a website’s own login challenge. The proxy consumes proxy credentials rather than forwarding them to the application.

Synthetic destinations must reach OuterSSH without local DNS resolution or direct-network fallback. SOCKS clients must send the hostname to the proxy rather than resolve it first. Decide explicitly which ordinary web destinations should use SSH and which should use the local network; this policy is outside the C library. Ensure the browser does not silently bypass intended remote-loopback traffic.

Rewriting options

OuterSSHHTTPProxyServerConfiguration has two independent options, both false by default:

  • rewrite_request_authorities translates Unix-socket authorities to localhost and encoded TCP aliases to their decoded destinations (such as 127.0.0.1:3000). It updates Host and matching source authorities in the request target, Origin, Referer, and Sec-WebSocket-Origin. Ordinary TCP destinations retain their authority. An unrelated origin is not simply replaced with localhost.
  • rewrite_loopback_urls_in_html replaces literal http:// and ws:// loopback URLs in eligible HTML responses from encoded endpoints with loopback aliases.

Outer Loop enables both options on macOS, iOS, and Linux. Windows enables only rewrite_request_authorities: WebView2 sends literal localhost URLs through the proxy when configured with --proxy-bypass-list="<-loopback>", but Unix-socket applications such as Jupyter still need the header translation. With HTML rewriting disabled, response bodies stream without rewrite inspection or buffering.

SOCKS does not rewrite HTTP headers. Framing and proxy authentication still apply to HTTP frontends when both rewriting options are disabled; such a frontend is not identical to a byte-transparent SOCKS connection.

HTML rewriting is bounded: the implementation buffers unencoded text/html bodies up to 2 MiB, and limits rewritten output to 8 MiB. Encoded responses, oversized bodies, or bodies that cannot be rewritten are passed through. The proxy does not decompress content. Rewriting is a byte transformation, not an HTML/JavaScript interpreter.

Response Location, cookie domains, and CORS/CSP policy headers do not receive a general reverse-authority rewrite. Separate JavaScript/JSON/CSS responses and dynamically constructed URLs are not covered by the HTML substitution. HTTPS contents cannot be rewritten. These are current compatibility limits, not promises that every localhost-oriented web application will work unchanged.

Framing, streaming, and tunnels

The frontend frames each HTTP exchange with llhttp. It handles Content-Length, chunked bodies, informational responses, HEAD, 204/304, and close-delimited responses. Request bodies stream; eligible response HTML may wait for the complete body. Body responses are serialized with chunked framing. Chunk extensions and trailers are consumed rather than forwarded.

Hop-by-hop headers and proxy authentication headers are removed as appropriate. Pipelined requests are serialized. An upstream connection is reused only for the same destination when the previous response permits it. A successful HTTP 101 upgrade becomes a raw tunnel, supporting WebSockets.

CONNECT initially establishes a tunnel. With either rewriting option enabled, the frontend recognizes plaintext HTTP/1.1 inside it and applies the same framing and rewriting. This covers Apple’s HTTP CONNECT proxy behavior and tunneled WebSocket handshakes. TLS and other protocols remain opaque.

For HTTPS, TLS still terminates in the browser and remote application. OuterSSH does not manufacture certificates, terminate TLS, or disable certificate checks. A synthetic hostname does not automatically match a service’s certificate. The frontend is not a general HTTP/2 or HTTP/3 implementation, although an opaque TLS tunnel can carry protocols negotiated by its endpoints. It does not expose UDP forwarding to a browser.

Browser-side compatibility remains separate

The Apple adapters inject LoopbackCompatibilityScript into eligible documents. It translates dynamically used loopback URLs in APIs including fetch, XMLHttpRequest, and WebSocket; it also restores friendlier display text. This script lives in the browser source, not in OuterSSH. The current Linux and Windows adapters do not install this same script.

The document-start session-context script, Outer Shell integration, custom navigation handling, and icon lookup are likewise product features. A new browser host should decide which it needs rather than assuming the HTTP proxy supplies them.

Minimal integration checks

Verify a new adapter with a remote TCP page and an allowlisted socket page; relative links; a cross-socket link; a form or large upload; a WebSocket; a loopback URL generated by JavaScript; and proxy authentication failure. Also check that another server’s page does not inherit cookies/storage, and that stopping the proxy does not send the same navigation directly through the local network.

Source references