Skip to content

Websocket

oRPC provides built-in WebSocket support for low-latency, bidirectional RPC.

Server Adapters

AdapterTarget
websocketMDN WebSocket API (Browser, Deno, Cloudflare Worker, etc.)
crosswsCrossws library (Node, Bun, Deno, SSE, etc.)
wsws library (Node.js)
bun-wsBun Websocket Server
ts
import { experimental_RPCHandler as RPCHandler } from '@orpc/server/websocket'

const handler = new RPCHandler(router)

Deno.serve((req) => {
  if (req.headers.get('upgrade') !== 'websocket') {
    return new Response(null, { status: 501 })
  }

  const { socket, response } = Deno.upgradeWebSocket(req)

  handler.upgrade(socket, {
    context: {}, // Provide initial context if needed
  })

  return response
})
ts
import { createServer } from 'node:http'
import { experimental_RPCHandler as RPCHandler } from '@orpc/server/crossws'

// any crossws adapter is supported
import crossws from 'crossws/adapters/node'

const handler = new RPCHandler(router)

const ws = crossws({
  hooks: {
    message: (peer, message) => {
      handler.message(peer, message, {
        context: {}, // Provide initial context if needed
      })
    },
    close: (peer) => {
      handler.close(peer)
    },
  },
})

const server = createServer((req, res) => {
  res.end(`Hello World`)
}).listen(3000)

server.on('upgrade', (req, socket, head) => {
  if (req.headers.upgrade === 'websocket') {
    ws.handleUpgrade(req, socket, head)
  }
})
ts
import { WebSocketServer } from 'ws'
import { experimental_RPCHandler as RPCHandler } from '@orpc/server/ws'

const handler = new RPCHandler(router)

const wss = new WebSocketServer({ port: 8080 })

wss.on('connection', (ws) => {
  handler.upgrade(ws, {
    context: {}, // Provide initial context if needed
  })
})
ts
import { experimental_RPCHandler as RPCHandler } from '@orpc/server/bun-ws'

const handler = new RPCHandler(router)

Bun.serve({
  fetch(req, server) {
    if (server.upgrade(req)) {
      return
    }

    return new Response('Upgrade failed', { status: 500 })
  },
  websocket: {
    message(ws, message) {
      handler.message(ws, message, {
        context: {}, // Provide initial context if needed
      })
    },
    close(ws) {
      handler.close(ws)
    },
  },
})
ts
import { experimental_RPCHandler as RPCHandler } from '@orpc/server/websocket'

const handler = new RPCHandler(router)

export class ChatRoom extends DurableObject {
  async fetch(): Promise<Response> {
    const { '0': client, '1': server } = new WebSocketPair()

    this.ctx.acceptWebSocket(server)

    return new Response(null, {
      status: 101,
      webSocket: client,
    })
  }

  async webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): Promise<void> {
    await handler.message(ws, message, {
      context: {}, // Provide initial context if needed
    })
  }

  async webSocketClose(ws: WebSocket): Promise<void> {
    handler.close(ws)
  }
}

INFO

Hibernation Plugin helps you fully leverage Hibernation APIs, making it especially useful for adapters like Cloudflare Websocket Hibernation.

Client Adapters

AdapterTarget
websocketMDN WebSocket API (Browser, Node, Bun, Deno, etc.)
ts
import { experimental_RPCLink as RPCLink } from '@orpc/client/websocket'

const websocket = new WebSocket('ws://localhost:3000')

const link = new RPCLink({
  websocket
})

TIP

Use partysocket library for manually/automatically reconnect logic.

INFO

This only shows how to configure the WebSocket link. For full client examples, see Client-Side Clients.

Released under the MIT License.