-
Notifications
You must be signed in to change notification settings - Fork 10.1k
Description
Describe the bug
I am using the new Bun engine as described here: https://socket.io/blog/bun-engine/
I am using it with hono, but i think that is irrelevant for this issue.
The problem is that i want to assosiate the connection with a session from the handshake. I might be doing this in a stupid way.
I am spinning up a Hono server, handling the socket.io connection request in the export and then when the client connection, the allowRequest function in the engine sees the headers and i can validate them, but then the headers are not present in the handshake in the socket middleware or in the socket.on("connection", ...) I have tried both.
To Reproduce
- Spin up a hono server with bun (see code)
- Do some auth (you need to have some headers)
- Connect a websocket from a client (i am using react (include credentials))
- Then look at the console.log from the allowRequest and the Connection and Middleware
- Only the allowRequest log shows any headers on the handshake request
Socket.IO server version: 4.5.z
Server
import { Hono } from "hono";
import { auth } from "./lib/auth";
import { Server as Engine } from "@socket.io/bun-engine";
import { Server } from "socket.io";
const app = new Hono();
const io = new Server();
const engine = new Engine({
path: "/[socket.io/](http://socket.io/)",
cors: {
origin: process.env.CORS_ORIGIN || "",
methods: ["GET", "POST"],
},
allowRequest: async (req, server) => {
console.log("Handshake headers:", req.headers); // <-- The headers are present
const session = await auth.api.getSession({ headers: req.headers });
console.log(session); // <-- This is a valid session
},
});
io.bind(engine);
io.use(async (socket, next) => {
const headers = socket.handshake.headers as unknown as Headers; // <-- The headers are NOT present
const session = await auth.api.getSession({ headers });
socket.data.session = session; // <-- This is NOT a valid session
next();
});
io.on("connection", async (socket) => {
console.log("New connection handshake headers:", socket.handshake);
socket.on("disconnect", () => {
console.log("Client disconnected");
});
});
...
...
...
export default {
port: 3000,
idleTimeout: 30, // must be greater than the "pingInterval" option of the engine, which defaults to 25 seconds
async fetch(req: Request, server: Bun.Server) {
const url = new URL(req.url);
if (url.pathname === "/socket.io/") {
return engine.handleRequest(req, server);
} else {
return app.fetch(req, server);
}
},
websocket,
};
Client
let socket: Socket | null = null;
function getBaseUrl() {
return process.env.NODE_ENV === "production"
? window.location.origin
: "http://localhost:3000";
}
function getSocket(): Socket {
if (typeof window === "undefined") {
throw new Error("getSocket() called during SSR");
}
if (!socket) {
socket = io(getBaseUrl(), {
withCredentials: true,
});
socket.on("connect", async () => {
console.log("[ws] connected", socket?.id);
});
socket.on("disconnect", (reason) => {
console.log("[ws] disconnected", reason);
});
}
return socket;
}
Expected behavior
I expected the headers from the handshake to be present in the connection and middleware function