workers-sdk icon indicating copy to clipboard operation
workers-sdk copied to clipboard

🐛 BUG: `Sec-WebSocket-Protocol` header not returned in WebSocket upgrade responses

Open mrbbot opened this issue 3 years ago • 1 comments

What version of Wrangler are you using?

2.0.28

What operating system are you using?

Mac

Describe the Bug

When returning a Response with a Sec-WebSocket-Protocol header, the protocol is never returned to the client.

Example

export default {
  async fetch(request) {
    const url = new URL(request.url);
    if (url.pathname === "/") {
      return new Response(
        `<script>
        const webSocket = new WebSocket("ws://localhost:8787/ws", ["protocol1", "protocol2", "protocol3"]);
        webSocket.addEventListener("open", () => {
          console.log(webSocket.protocol);
        });
        </script>`,
        { headers: { "Content-Type": "text/html; charset=utf-8" } }
      );
    } else if (url.pathname === "/ws") {
      const [client, worker] = Object.values(new WebSocketPair());
      worker.accept();
      return new Response(null, {
        status: 101,
        webSocket: client,
        headers: { "Sec-WebSocket-Protocol": "protocol2" },
      });
    } else {
      return new Response(null, { status: 404 });
    }
  },
};

Running wrangler dev, visiting http://localhost:8787 in the browser, and opening the JavaScript console shows an empty string. However protocol2 should be logged.

mrbbot avatar Sep 03 '22 15:09 mrbbot

The title of this issue, while accurate, doesn’t quite capture the impact or severity. The impact is that a common pattern of relying on Sec-WebSocket-Protocol for auth does not work with wrangler 2. Code that currently works in production and with wrangler 1 does not work with wrangler 2. The severity is not just limited to the inconvenience of our not being able to develop with wrangler 2, but extends to ~all our customers developing locally with wrangler. (We sell a DO-based multiplayer system that our customers run themselves so they too are impacted.)

Possibly this is a known issue because there is this comment in the wrangler proxy code. We have temporarily worked around it by modifying the wrangler source code to fix the bug in the following way. We also had to pin Wrangler 2.0.24 into our product and recommend that customers use the pinned version via npx wrangler ... from inside our project, rather than latest.

Note this is a different flavor of a bug that was previously fixed in miniflare. In that bug, in local mode, if a custom Sec-WebSocket-Protocol header was added by the server, that header would be (incorrectly) duplicated by miniflare (but not in non-local mode). In this new bug, if a Sec-WebSocket-Protocol header is added by the server, the wrangler2 proxy drops it.

Please let us know if there’s any other information we can provide that would be helpful. Thanks!

phritz avatar Sep 21 '22 01:09 phritz