Skip to content

Commit a283836

Browse files
fix: websockets (#522)
This fixes websockets in `wrangler dev`. It looks like we broke it in #503. I've reverted the specific changes made to `proxy.ts`. Test plan - ``` cd packages/wrangler npm run build cd ../workers-chat-demo npx wrangler dev ```
1 parent 5947bfe commit a283836

File tree

5 files changed

+117
-10
lines changed

5 files changed

+117
-10
lines changed

.changeset/empty-trains-mix.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
fix: websockets
6+
7+
This fixes websockets in `wrangler dev`. It looks like we broke it in https://github.com/cloudflare/wrangler2/pull/503. I've reverted the specific changes made to `proxy.ts`.
8+
9+
Test plan -
10+
11+
```
12+
cd packages/wrangler
13+
npm run build
14+
cd ../workers-chat-demo
15+
npx wrangler dev
16+
17+
```

package-lock.json

+75
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/wrangler/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"command-exists": "^1.2.9",
6767
"devtools-protocol": "^0.0.955664",
6868
"execa": "^6.0.0",
69+
"faye-websocket": "^0.11.4",
6970
"finalhandler": "^1.1.2",
7071
"find-up": "^6.2.0",
7172
"ignore": "^5.2.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module "faye-websocket" {
2+
/**
3+
* Standards-compliant WebSocket client and server.
4+
*/
5+
export default WebSocket;
6+
}

packages/wrangler/src/proxy.ts

+18-10
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { createServer } from "node:http";
22
import { connect } from "node:http2";
3+
import WebSocket from "faye-websocket";
34
import { useEffect, useRef, useState } from "react";
45
import serveStatic from "serve-static";
5-
import WebSocket from "ws";
66
import type { CfPreviewToken } from "./api/preview";
77
import type {
88
IncomingHttpHeaders,
@@ -12,6 +12,12 @@ import type {
1212
Server,
1313
} from "node:http";
1414
import type { ClientHttp2Session, ServerHttp2Stream } from "node:http2";
15+
import type ws from "ws";
16+
17+
interface IWebsocket extends ws {
18+
// Pipe implements .on("message", ...)
19+
pipe<T>(fn: T): IWebsocket;
20+
}
1521

1622
/**
1723
* `usePreviewServer` is a React hook that creates a local development
@@ -199,24 +205,26 @@ export function usePreviewServer({
199205
requestResponseBufferRef.current = [];
200206

201207
/** HTTP/1 -> WebSocket (over HTTP/1) */
202-
const handleUpgrade = (message: IncomingMessage, socket: WebSocket) => {
208+
const handleUpgrade = (
209+
message: IncomingMessage,
210+
socket: WebSocket,
211+
body: Buffer
212+
) => {
203213
const { headers, url } = message;
204214
addCfPreviewTokenHeader(headers, previewToken.value);
205215
headers["host"] = previewToken.host;
206-
const localWebsocket = WebSocket.createWebSocketStream(socket);
216+
const localWebsocket = new WebSocket(message, socket, body) as IWebsocket;
207217
// TODO(soon): Custom WebSocket protocol is not working?
208-
const remoteWebsocket = new WebSocket(
218+
const remoteWebsocketClient = new WebSocket.Client(
209219
`wss://${previewToken.host}${url}`,
210220
[],
211221
{ headers }
212-
);
213-
const remoteWebsocketStream =
214-
WebSocket.createWebSocketStream(remoteWebsocket);
215-
localWebsocket.pipe(remoteWebsocketStream).pipe(localWebsocket);
222+
) as IWebsocket;
223+
localWebsocket.pipe(remoteWebsocketClient).pipe(localWebsocket);
216224
// We close down websockets whenever we refresh the token.
217225
cleanupListeners.push(() => {
218-
socket.close();
219-
remoteWebsocket.close();
226+
localWebsocket.close();
227+
remoteWebsocketClient.close();
220228
});
221229
};
222230
proxy.on("upgrade", handleUpgrade);

0 commit comments

Comments
 (0)