52 lines
1.8 KiB
TypeScript
52 lines
1.8 KiB
TypeScript
import config from "config";
|
|
import cookie from "cookie";
|
|
import cookieParser from "cookie-parser";
|
|
import {Request} from "express";
|
|
import {Session} from "express-session";
|
|
import {IncomingMessage} from "http";
|
|
import {WebSocket} from "ws";
|
|
|
|
import Application from "./Application.js";
|
|
import RedisComponent from "./components/RedisComponent.js";
|
|
import {logger} from "./Logger.js";
|
|
import WebSocketListener from "./WebSocketListener.js";
|
|
|
|
export default abstract class SessionWebSocketListener<A extends Application> extends WebSocketListener<A> {
|
|
|
|
public async handle(socket: WebSocket, request: IncomingMessage): Promise<void> {
|
|
socket.once('message', (data, isBinary) => {
|
|
if (isBinary) return socket.close(1003);
|
|
|
|
const cookies = cookie.parse(data.toString());
|
|
const sid = cookieParser.signedCookie(cookies['connect.sid'], config.get('session.secret'));
|
|
|
|
if (!sid) {
|
|
socket.close(1002, 'Could not decrypt provided session cookie.');
|
|
return;
|
|
}
|
|
|
|
const store = this.getApp().as(RedisComponent).getStore();
|
|
store.get(sid, (err, session) => {
|
|
if (err || !session) {
|
|
logger.error(err, 'Error while initializing session in websocket for sid ' + sid);
|
|
socket.close(1011);
|
|
return;
|
|
}
|
|
|
|
session.id = sid;
|
|
|
|
store.createSession(<Request>request, session);
|
|
this.handleSessionSocket(socket, request, session as Session).catch(err => {
|
|
logger.error(err, 'Error in websocket listener.');
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
protected abstract handleSessionSocket(
|
|
socket: WebSocket,
|
|
request: IncomingMessage,
|
|
session: Session,
|
|
): Promise<void>;
|
|
}
|