Relay HTTP
The browser calls an application-owned URL below /cooperative-portal/relay/{session_id}/. It never connects directly to the local origin. The broker validates the active session and route exposure, sends one ordinary Cheetah RPC command to the bound connector, and turns the returned payload into a browser-facing HTTP response.
Each boundary deliberately carries only a subset of HTTP and Cheetah state. The diagram is a contract map, not a claim of transparent proxying.
The request contract is bounded
cooperative_site_http_request contains the session and site IDs, GET, HEAD, or POST, an absolute path beginning with /, exactly one query representation, selected headers, and an optional base64 body.
Browser requests preserve their visible query bytes in raw_query. Programmatic callers may use either raw_query or query: Record<string, string[]>, never both. The raw form excludes the leading ?, fragments, controls, spaces, and non-ASCII characters, and is limited to 16,384 characters. A fragment is browser-local and is never sent to the origin.
The console connector resolves the path below its normalized local_origin or explicit application_metadata.upstream_origin. It rejects network-path references, backslashes, embedded queries or fragments, controls, non-HTTP schemes, foreign origins, and paths that escape the configured base path. The in-process loopback executor similarly rejects ambiguous or encoded prefix escapes.
This confinement protects the connector machine's network authority. Route patterns remain a second, application-level allowlist; origin confinement does not make a broad route policy wise.
Only selected HTTP state crosses
The supplied implementations forward these request headers:
accept;content-type;if-none-match;if-modified-since.
They do not forward the browser's Host, Authorization, cookies, forwarding headers, or arbitrary application headers. The connector performs local HTTP with redirect following disabled.
The connector records local Set-Cookie values in a jar scoped by relay session. Matching cookies are sent only to later local requests in that session; they are not returned to the remote browser. The jar models cookie name, value, and path. It does not implement domain, expiry, Secure, SameSite, or multiple same-name cookies on different paths, so it is not a browser-equivalent cookie store.
On the return path, the broker removes content-length, set-cookie, hop-by-hop/framing headers, content-security-policy headers, and CORS headers that no longer describe the viewer-facing origin. A root-relative or same-local-origin Location is rewritten into the session relay path. A foreign absolute Location intentionally leaves relay space in the viewer's browser; the connector does not fetch it.
Bodies are inline
The connector returns an HTTP status, selected headers, and either an inline base64 body or an empty body. HEAD, 204, and 304 are bodyless. The Python model names a reference body mode, but neither the current connector nor gateway implements it. Large site responses therefore travel inside ordinary command results and remain subject to command, history, and transport limits.
This is different from command-parameter payload references. auto_offload=True helps supported command values on the Cheetah path; it does not turn an arbitrary relayed HTTP response into a streaming or externally referenced body.
HTML compatibility is deliberately partial
With application_metadata.html_compat_mode set to root_relative_bridge, the broker rewrites root-relative href, src, and action attributes, rewrites compatible redirects, and injects a small browser shim for fetch, XHR, and history URLs.
It does not understand every URL in CSS, JavaScript, module graphs, service-worker scopes, custom URL construction, WebSockets, or streaming APIs. Prefer a local application that can operate below a configurable base path. Use the bridge only after exercising the application's real navigation, assets, forms, and error paths.
Failures keep their layer
An absent or disconnected connector becomes 503; connector timeout becomes 504; dispatch or malformed connector results become 502. A denied route becomes 403, and a revoked session becomes 410. These are relay failures with structured details.
An origin's ordinary HTTP response keeps its status. Responses of 500 or above also receive an upstream_http_error detail, but they are not confused with command-transport failure. All relay commands still use ordinary dispatch, client acknowledgement, correlation, and history, so a local timeout must be reconciled using the same delivery-evidence rules as other external effects.
Next: Sessions and sharing.