shiichan

Workers の WebSocket、Close フレームに自分で返事してくれるようになったよ!

やっほー、しぃちゃんだよ!今日は WebSocket まわりの地味だけど嬉しい変更を見つけたから、みんなに紹介しちゃうね。

Cloudflare Changelog developers.cloudflare.com

なにが発表されたの?

Cloudflare の Changelog から。Workers ランタイムが、相手(peer)から Close フレームを受け取ったときに、自動で返しの Close フレームを送ってくれるようになったよ。これで readyStateclose イベントが発火する前に CLOSED に変わるの。この挙動は WebSocket 仕様 や普通のブラウザの動きとちゃんと揃っているんだ。

今までどうだったの?

これまでは Close フレームを受け取っても、コード側で自分で close() を呼んであげないと、仕様どおりの相互 Close にならないことがあったの。「受け取ったら返す」というお約束を、開発者が手で書く必要があったんだね。

これで何が変わるの?

close イベントの中で自分で close() を呼んでいた既存のコードは、そのまま動くから安心してね。もう閉じ終わっている WebSocket への close() 呼び出しは、静かに無視されるだけなの。

つまり「返しの Close を送る」という後始末を、ランタイムが代わりにやってくれるようになったってこと。イベントが届いた時点でもう readyStateCLOSED だから、わざわざ close() を書かなくてよくなったよ。

深く潜ってみよう

この挙動は、互換性日付(compatibility date)が 2026-04-07 以降の Workers でデフォルト有効になるよ(web_socket_auto_reply_to_close 互換性フラグ 経由)。

ただし、Worker がクライアントとバックエンドの間に立つ WebSocket プロキシだと、両側の Close を自分のタイミングで調整したいことがあるよね。そういうときは accept(){ allowHalfOpen: true } を渡すの。そうすると close イベントの中でも readyStateCLOSING のままになって、好きなタイミングで自分で server.close() を呼べるようになるよ。

const [client, server] = Object.values(new WebSocketPair());

server.accept({ allowHalfOpen: true });

server.addEventListener("close", (event) => {
  // readyState is still CLOSING here.
  server.close(event.code, "done");
});

もっと知りたい人は WebSockets の Close の挙動 を読んでみてね。

まとめ

  • Workers が Close フレームに自動で返信するようになった(仕様やブラウザと同じ挙動)
  • 互換性日付 2026-04-07 以降でデフォルト有効。手動の close() は無視されるから既存コードは安全
  • プロキシ用途なら accept({ allowHalfOpen: true }) で従来どおり手動で調整できる
  • WebSocket をゴリゴリ使っている Workers 開発者に、じんわり刺さるアップデートだよ!