Skip to content

Relay HTTP endpoints ​

The Relay exposes Chromium-shaped HTTP discovery alongside its WebSocket endpoints. The Node adapter (serveRelay, in src/relay/node.ts) runs two HTTP servers: a browser/CDP server for Client discovery and raw CDP traffic, and a Host server for the Host uplink plus optional fallback HTTP. The JSON payloads come from RelayCore (jsonVersion(), jsonList(), status()), so another runtime adapter can serve the same shapes.

The four discovery routes below live on the browser/CDP server. They respond with Content-Type: application/json; charset=utf-8 and HTTP status 200; any other browser/CDP HTTP path returns 404. The Host server does not serve these routes. Set ICDP_DEBUG=1 to log every HTTP request and WebSocket upgrade.

GET routes ​

PathHandlerBody
/json/versionRelayCore.jsonVersion()Browser version descriptor
/jsonRelayCore.jsonList()Array of target descriptors
/json/listRelayCore.jsonList()Same array as /json
/icdp/statusRelayCore.status()Relay status snapshot

Any other browser/CDP HTTP path is answered with HTTP 404 and the body not found. The optional fallback handler only runs on the Host server.

GET /json/version ​

The browser version descriptor a Client reads to discover the WebSocket endpoint.

json
{
  "Browser": "icdp/0.5.1",
  "Protocol-Version": "1.3",
  "User-Agent": "icdp/0.5.1",
  "V8-Version": "synthetic",
  "WebKit-Version": "synthetic",
  "webSocketDebuggerUrl": "ws://127.0.0.1:9229/devtools/browser"
}
FieldTypeValue
BrowserstringThe product string (default icdp/0.5.1).
Protocol-Versionstring"1.3", fixed.
User-AgentstringThe product string.
V8-Versionstring"synthetic", fixed.
WebKit-Versionstring"synthetic", fixed.
webSocketDebuggerUrlstringAbsolute URL of the browser WebSocket endpoint (browserWsUrl).

GET /json and GET /json/list ​

Both paths return the same array, one entry per Target the Relay currently knows about.

json
[
  {
    "description": "icdp iframe target",
    "devtoolsFrontendUrl": "",
    "id": "playground",
    "title": "Playground",
    "type": "page",
    "url": "http://127.0.0.1:3001/playground",
    "webSocketDebuggerUrl": "ws://127.0.0.1:9229/devtools/page/playground"
  }
]
FieldTypeValue
descriptionstring"icdp iframe target", fixed.
devtoolsFrontendUrlstring"", fixed.
idstringThe targetId.
titlestringThe Target's last-known title.
typestring"page", fixed.
urlstringThe Target's last-known URL.
webSocketDebuggerUrlstringDirect WebSocket for this Target. Omitted only when a custom RelayCore adapter does not configure targetWsUrl.

Two connection forms

/json/version advertises the browser endpoint for explicit flat Sessions. Each list entry advertises a direct Target endpoint whose implicit commands and events omit sessionId. See the flat-session protocol for both forms.

GET /icdp/status ​

A snapshot of Relay state, for health checks and the playground status page.

json
{
  "hostConnected": true,
  "targets": [
    { "targetId": "playground", "title": "Playground", "url": "http://127.0.0.1:3001/playground" }
  ],
  "clients": 2
}
FieldTypeValue
hostConnectedbooleantrue when a Host uplink is attached.
targetsTargetSummary[]Each entry is { targetId, title, url }. See protocol types.
clientsnumberCount of connected Clients.

WebSocket upgrade paths ​

The Relay accepts browser and direct Target upgrades on the browser/CDP server, plus the Host uplink on the Host server. All defaults are configurable through ServeRelayOptions.

ServerPath optionDefaultRoleAdapter call
browser/CDPbrowserPath/devtools/browserClient connection (raw CDP JSON)clientConnected / clientMessage / clientDisconnected
browser/CDPtargetPathPrefix/devtools/page/<targetId>Direct Target connection (sessionless implicit Session)clientConnected(socket, targetId) / clientMessage / clientDisconnected
HosthostPath/icdp/hostHost uplink (bridge protocol)hostConnected / hostMessage / hostDisconnected

An upgrade on any other path is rejected: the socket is destroyed without an HTTP response. Only one validated Host is served at a time. A new Host socket remains a contender until its ready frame passes bridge validation, then it replaces the previous Host. The browser path appears in /json/version; per-Target paths appear in /json and /json/list.

The full URLs are read back from the RelayServer returned by serveRelay:

ts
import { serveRelay } from "@olimsaidov/icdp/relay/node";

const relay = await serveRelay({ hostPort: 3000, browserPort: 9229 });
relay.hostWsUrl;    // ws://127.0.0.1:3000/icdp/host          (Host uplink)
relay.browserWsUrl; // ws://127.0.0.1:9229/devtools/browser  (Clients)
relay.targetWsUrl("preview"); // ws://127.0.0.1:9229/devtools/page/preview

See the Relay reference for the RelayCore adapter API and the ServeRelayOptions fields that set ports, hostnames, paths, advertised URLs, product, and fallback.

Released under the MIT License.