Adapters

Cloudflare

Integrate crossws with Cloudflare Workers.


To integrate crossws with your Cloudflare Workers, you need to check for the upgrade header.

For pub/sub support, you need to use Durable objects.
import crossws from "crossws/adapters/cloudflare";

const ws = crossws({
  hooks: {
    message: console.log,
  },
});

export default {
  async fetch(request, env, context) {
    if (request.headers.get("upgrade") === "websocket") {
      return ws.handleUpgrade(request, env, context);
    }
    return new Response(
      `<script>new WebSocket("ws://localhost:3000").addEventListener("open", (e) => e.target.send("Hello from client!"));</script>`,
      { headers: { "content-type": "text/html" } },
    );
  },
};

Adapter Hooks

  • cloudflare:accept (peer)
  • cloudflare:message (peer, event)
  • cloudflare:error (peer, event)
  • cloudflare:close (peer, event)
See test/fixture/cloudflare.ts for demo and src/adapters/cloudflare.ts for implementation.

Durable objects

To integrate crossws with Cloudflare Durable Objects (available on paid plans) with pub/sub and hibernation support, you need to check for the upgrade header and additionally export a Durable object with crossws adapter hooks integrated.

import { DurableObject } from "cloudflare:workers";
import crossws from "crossws/adapters/cloudflare-durable";

const ws = crossws({
  // bindingName: "$DurableObject",
  // instanceName: "crossws",
  hooks: {
    message: console.log,
    open(peer) {
      peer.subscribe("chat");
      peer.publish("chat", { user: "server", message: `${peer} joined!` });
    },
  },
});

export default {
  async fetch(request, env, context) {
    if (request.headers.get("upgrade") === "websocket") {
      return ws.handleUpgrade(request, env, context);
    }
    return new Response(
      `<script>new WebSocket("ws://localhost:3000").addEventListener("open", (e) => e.target.send("Hello from client!"));</script>`,
      { headers: { "content-type": "text/html" } },
    );
  },
};

export class $DurableObject extends DurableObject {
  fetch(request) {
    return ws.handleDurableUpgrade(this, request);
  }

  webSocketMessage(client, message) {
    return ws.handleDurableMessage(this, client, message);
  }

  webSocketClose(client, code, reason, wasClean) {
    return ws.handleDurableClose(this, client, code, reason, wasClean);
  }
}

Update your wrangler.toml to specify Durable object:

[[durable_objects.bindings]]
name = "$DurableObject"
class_name = "$DurableObject"

[[migrations]]
tag = "v1"
new_classes = ["$DurableObject"]