Documentation/frontend/Transports
In this section

Transports

Choose the transport the service exposes at the URL you are calling. A gateway can serve HTTP RPC at one path and WebSocket upgrades at another.

ClientUse it forTransport selection
createClient / NetronClientFramework-independent RPC to one backendhttp by default, or explicit websocket
HttpClientHTTP RPC with authentication or custom middlewareHTTP
WebSocketClientBinary RPC, server-initiated tasks and reconnect eventsWebSocket
createMultiBackendClientSeveral backends with separate endpoints and policiesConfigure http or websocket per backend
NetronReactClientReact queries, mutations and event subscriptionshttp, websocket or React-specific auto

HTTP

Supply an absolute base URL. The browser client appends /netron/invoke and sends a JSON POST. HTTP connect() initializes the client locally. To check whether a service is reachable, invoke a permitted read or its readiness probe.

import { createClient } from '@omnitron-dev/netron-browser';

const client = createClient({
  url: new URL('/api', window.location.origin).href,
  transport: 'http',
  timeout: 10_000,
  headers: { 'X-Client': 'web/1.0' },
  http: { retry: true, maxRetries: 3, redirect: 'error' },
});
await client.connect();

Invocation lifetime and replay

const controller = new AbortController();
const result = await client.invoke('Catalog', 'list', [], {
  signal: controller.signal,
  timeout: 10_000,
  idempotent: true,
});

signal is local control state, never part of the wire payload. Cancellation rejects with signal.reason. The deadline covers transport attempts, backoff, response-body decoding and response middleware. A response whose headers arrive before the deadline can still time out while its body is being read. Cancellation and deadline expiry do not trigger network retry or auth refresh. Aborting the caller does not roll back an operation already accepted by the server.

Network retries require both client http.retry: true and invocation idempotent: true. The second option is the caller's assertion about the operation, not an idempotency key or a server deduplication guarantee. Do not set it for a write merely because a failed connection returned no answer. Use a domain operation ID with server-side replay semantics when a write must be retried. The direct HTTP client does not infer this property from a method name.

For a fixed RPC endpoint, use http.redirect on createClient or pass redirect: 'error' directly to HttpClient. Fetch then rejects a redirect before replaying the request at another address. This protects publication bodies and custom credential headers. With multiple backends, set http.redirect on the backend that needs this policy. Omitting the option preserves the default Fetch redirect behavior.

Service query hooks forward the query cancellation signal. A component unmount does not automatically cancel a mutation: its server-side outcome may already be committed.

HTTP wire format

The direct browser transport posts JSON to /netron/invoke:

{"id":"request-id","service":"Catalog","method":"list","input":[]}

A successful reply contains the same id, success: true, and data. A failed invocation contains success: false and a structured error. Titan may also reject a request before RPC admission with an HTTP transport error. The client distinguishes that refusal from a successful RPC envelope. A mismatched ID, malformed envelope or an HTTP failure carrying an RPC success is rejected. Application payloads still require their own runtime schemas; a TypeScript return type cannot validate bytes received over the network.

WebSocket

Use the URL of a binary Netron WebSocket listener. Await connect() before issuing calls. It waits for the Netron handshake. Use the direct client for connection events, service discovery or server-initiated task handlers.

import { WebSocketClient } from '@omnitron-dev/netron-browser';

const socket = new WebSocketClient({
  url: 'wss://api.example.com/rpc',
  enableServiceDiscovery: true,
  reconnect: true,
  reconnectInterval: 1_000,
  maxReconnectAttempts: 12,
});

socket.on('reconnecting', ({ attempt, delay, announced }) => {
  console.info(announced ? 'Server restarting' : 'Connection lost', { attempt, delay });
});
await socket.connect();
try {
  const items = await socket.invoke('Catalog@1.0.0', 'list', []);
  console.info(items);
} finally {
  await socket.disconnect();
}

Service discovery resolves a service's wire definition ID on the connected server. It is opt-in. Only enable it for a trusted endpoint. Alternatively, supply a known serviceDefinitions map. Register a named server-initiated task with socket.onTask(name, handler) when the service contract requires it.

Reconnect behaviour

Automatic reconnect is enabled by default. The base retry interval is 1,000 ms and the default attempt limit is Infinity. Ordinary retries use exponential backoff with jitter, capped at 30 seconds with the default base. A server restart announced by close code 1012 gets an initial jittered delay of 1–3 seconds. The reconnecting event exposes the actual delay. Exhausting a finite limit sets the state to failed and emits reconnect-failed. Explicit disconnect() ends the reconnect loop.

A closed socket rejects its pending invocations. For an interrupted write, check its recorded outcome before submitting it again. For events, the React subscription manager re-registers subscribed names after reconnect. Recover events missed during the outage using the service's cursor or a fresh snapshot.

React transport selection

Use transport: 'http' for an HTTP-only API, including a React application behind an HTTP gateway. Use 'websocket' for a WebSocket-only service.

NetronReactClient defaults to 'auto'. Without a browser window it selects HTTP. In the browser it opens WebSocket first, waits for the handshake, then initializes HTTP with the same configured URL. Calls prefer the connected WebSocket and can use the initialized HTTP client while the socket is down. If the initial WebSocket connection fails, connect() rejects before HTTP initialization. For this mode, supply an absolute HTTP(S) base that serves both the WebSocket upgrade and the HTTP RPC path. For separate endpoints, configure each backend explicitly.

Connection state and metrics

The direct browser clients expose getState() and getMetrics(). Connection states are disconnected, connecting, connected, reconnecting and failed. A React component inside NetronProvider can read state, error and reconnect from useNetronConnection().

const { transport, state, requestsSent, responsesReceived, errors, avgLatency } =
  client.getMetrics();

These counters belong to this client. avgLatency is optional and measured in milliseconds. Use a query cache or the fluent HTTP interface when individual reads require caching or deduplication.

See also