Task:
I'm using NestJS and trying to find information on how to set the socket.id as a cookie for every client who has connected to the server.
Simplified code slices:
I found this code example in the documentation:
const io = new Server(httpServer, {
cookie: true
});
// is similar to
const io = new Server(httpServer, {
cookie: {
name: "io",
path: "/",
httpOnly: true,
sameSite: "lax"
}
});
So, since I don't use Express.js(and native Node.js), but use Nest.js, I've tried to adjust the above-mentioned code as follows:
// event.gateway.ts file
@WebSocketGateway({
namespace: "api/chat",
cors: {
origin: "*",
},
})
export class EventGateway
implements OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit
{
@WebSocketServer()
server: Namespace<IClientToServerEvents, IServerToClientEvents>;
afterInit(server: Namespace) {
console.log("server: ", server);
server.server.engine.opts.cookie = {
name: "io",
path: "/",
httpOnly: true,
sameSite: "lax",
};
}
// other code...
}
There were no typescript errors when checking the code, and there were no javascript errors after creating the application.
I tried to find the Set-Cookie header when initializing the connection. So, this is it, but as you can see they weren't set:
Possible workarounds:
P.S:
It looks like socket cookies are different from the HTTP cookies. So, please tell me, which way I should use to set socket.id value as an HTTP cookie?
It seems like there is no well-trodden path to follow.
And I found out that Websocket cookies are different from HTTP cookies.
So, the best approach to handle with this task is:
After establishing the websocket connection, in websocket "on connect" event, the frontend should simply sends an HTTP request, e.g., http://localhost3000/api/set-socket-id
, and lay the socketId in the request body. Then, the backend will set the socketId as an HttpOnly cookie.
Here is code example:
// frontend
this.socket.on("connect", async () => {
await fetch("http://localhost3000/api/set-socket-id", {
method: "POST",
credentials: "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({ socketId: this.socket.id }),
});
});
// backend
@Post("set-socket-id")
@UseGuards(AuthGuard)
setSocketId(
@Req() request: Request,
@Res() response: Response,
@Body("socketId") socketId: string
) {
response.cookie("socket_id", socketId, {
path: "/",
httpOnly: true,
sameSite: "lax",
});
response.sendStatus(200);
}