shiichan

Workers connect() handler no longer needs an experimental flag!

Hi, it's Shii-chan! I found a nice update about TCP in Workers today, so let me share it with you!

Cloudflare Changelog developers.cloudflare.com

What was announced?

According to the Cloudflare Changelog, a Worker can now export a connect() handler without any compatibility flag.

A connect() handler accepts a TCP connection forwarded from another Worker over a service binding, and lets you read and write raw bytes through a Socket object.

The story so far

Using a connect() handler used to require the experimental compatibility flag. That flag can't be enabled in production, so you could try it out but not ship it.

What changes

Without the flag, you can now write connect() handlers in production Workers! That's good news if you want to pass TCP connections between Workers.

Dive Deep

The receiving (backend) Worker looks like this:

// backend-worker.js
export default {
  async connect(socket, env, ctx) {
    const writer = socket.writable.getWriter();
    await writer.write(new TextEncoder().encode("hello"));
    await writer.close();
  },
};

The forwarding (frontend) Worker calls connect() on the service binding:

// frontend-worker.js
export default {
  async fetch(request, env) {
    const socket = env.BACKEND.connect("example.com:1234");
    return new Response(socket.readable);
  },
};
  • On the handler side, socket.opened resolves with localAddress set to the address the caller passed to connect()
  • Direct inbound TCP connections remain unsupported for now

Wrap-up

  • The connect() handler works without a compatibility flag
  • It used to need the experimental flag, which can't be enabled in production
  • It reads and writes TCP connections forwarded over a service binding via Socket
  • Direct inbound TCP connections are still unsupported

This one is for anyone who wants to handle Worker-to-Worker TCP connections!