Patrick (he/him)
Patrick (he/him)17mo ago

WebSocket subprotocols

This might be a bug: Deno's websocket implementation seems to have issues with subprotocols (RFC section on subprotocol). I was using one initially, then I removed it and that issue seems to be resolved. With the subprotocol, since the one returned by Deno.upgradeWebSocket does not include the sec-websocket-protocol header, and response headers are immutable, I was instantiating a new Response instance, copying over data from the response returned by upgradeWebSocket and adding the sec-websocket-protocol header. Even then, the websocket in Deno never opened and all of its properties including readyState would remain undefined indefinitely. The browser was happy, though: its websocket instance's open event was firing, only the server never could use its websocket instance. I removed the subprotocols parameter to the websocket constructor and the code on the server handing it and now the server's websocket is opening and messages are flowing. server:
import { serve } from "http";

serve((request) => {
if (request.headers.get("sec-websocket-protocol") === "esm-hmr") {
const { socket, response } = Deno.upgradeWebSocket(request);
// <Do stuff with socket>

// Create new response with proper headers
return new Response(null, {
status: response.status,
statusText: response.statusText,
headers: {
connection: response.headers.get("connection")!,
"sec-websocket-accept": response.headers.get("sec-websocket-accept")!,
upgrade: response.headers.get("upgrade")!,
"sec-websocket-protocol": "esm-hmr"
}
})
} else {
return new BadRequestResponse()
}
})
import { serve } from "http";

serve((request) => {
if (request.headers.get("sec-websocket-protocol") === "esm-hmr") {
const { socket, response } = Deno.upgradeWebSocket(request);
// <Do stuff with socket>

// Create new response with proper headers
return new Response(null, {
status: response.status,
statusText: response.statusText,
headers: {
connection: response.headers.get("connection")!,
"sec-websocket-accept": response.headers.get("sec-websocket-accept")!,
upgrade: response.headers.get("upgrade")!,
"sec-websocket-protocol": "esm-hmr"
}
})
} else {
return new BadRequestResponse()
}
})
client:
const socket = new WebSocket(socketURL, "esm-hmr");
const socket = new WebSocket(socketURL, "esm-hmr");
2 Replies
ioB
ioB17mo ago
Code would be really nice (might be useful for a test case!)
Patrick (he/him)
Patrick (he/him)17mo ago
server code:
import { serve } from "http";

serve((request) => {
if (request.headers.get("sec-websocket-protocol") === "esm-hmr") {
const { socket, response } = Deno.upgradeWebSocket(request);
// <Do stuff with socket>

// Create new response with proper headers
return new Response(null, {
status: response.status,
statusText: response.statusText,
headers: {
connection: response.headers.get("connection")!,
"sec-websocket-accept": response.headers.get("sec-websocket-accept")!,
upgrade: response.headers.get("upgrade")!,
"sec-websocket-protocol": "esm-hmr"
}
})
} else {
return new NotFoundResponse()
}
})
import { serve } from "http";

serve((request) => {
if (request.headers.get("sec-websocket-protocol") === "esm-hmr") {
const { socket, response } = Deno.upgradeWebSocket(request);
// <Do stuff with socket>

// Create new response with proper headers
return new Response(null, {
status: response.status,
statusText: response.statusText,
headers: {
connection: response.headers.get("connection")!,
"sec-websocket-accept": response.headers.get("sec-websocket-accept")!,
upgrade: response.headers.get("upgrade")!,
"sec-websocket-protocol": "esm-hmr"
}
})
} else {
return new NotFoundResponse()
}
})
client code:
const socket = new WebSocket(socketURL, "esm-hmr");
const socket = new WebSocket(socketURL, "esm-hmr");
@timpost or @spam.wizrad, this might be one of the quirks or gaps with current WS support