hexabot/api/src/websocket/utils/socket-request.ts
2024-09-10 10:50:11 +01:00

133 lines
3.9 KiB
TypeScript

/*
* Copyright © 2024 Hexastack. All rights reserved.
*
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
* 3. SaaS Restriction: This software, or any derivative of it, may not be used to offer a competing product or service (SaaS) without prior written consent from Hexastack. Offering the software as a service or using it in a commercial cloud environment without express permission is strictly prohibited.
*/
// Import required modules and configurations
import { SessionData } from 'express-session';
import { Socket } from 'socket.io';
import { SubscriberStub } from '@/chat/schemas/subscriber.schema';
import { config } from '@/config';
import { User } from '@/user/schemas/user.schema';
import { IOIncomingMessage } from '../pipes/io-message.pipe';
// Define the SocketRequest class for managing incoming socket requests
export class SocketRequest {
// Default properties related to the connection type and protocols
transport: string = 'socket.io';
protocol: string = 'ws';
isSocket: boolean = true;
// Networking properties
ip: string;
ips: string[];
port: number | null = null;
// Socket and URL data
socket: Socket;
url: string;
path: string;
query: Record<string, any>;
// Request specifics
method: string;
body: Record<string, any>;
headers: {
host?: string;
cookie?: string;
nosession?: boolean;
origin?: string;
['user-agent']?: string;
[key: string]: string | boolean | undefined;
};
sessionID: string;
private _session: SessionData<SubscriberStub>;
get session() {
return this._session;
}
set session(data: SessionData<SubscriberStub>) {
this._session = data;
this.socket.data.session = data;
}
// User information
user: User;
// Constructor to initialize a new socket request
constructor(
socket: Socket,
method: string,
incomingMessage: IOIncomingMessage,
) {
// Set IP and possible IPs list from the socket handshake information
this.ip = socket.handshake.address;
this.ips =
'ips' in socket.handshake
? (socket.handshake.ips as string[])
: [this.ip];
// Reference to the socket and the URL from the incoming message
this.socket = socket;
this.url = incomingMessage.url;
// Resolve the URL and path
const urlObj = new URL(
this.url.startsWith('http')
? this.url
: `${config.parameters.apiUrl}${this.url}`,
);
this.path = urlObj.pathname || '/';
// Combine query parameters from URL and socket handshake
const urlQuery = Array.from(urlObj.searchParams).reduce(
(acc, [key, value]) => {
acc[key] = value;
return acc;
},
{} as Record<string, any>,
);
this.query = {
...socket.handshake.query,
...urlQuery,
};
// Set the HTTP method and the body of the request
this.method = method.toUpperCase();
this.body = Array.isArray(incomingMessage.data)
? incomingMessage.data
: { ...(incomingMessage.params || {}), ...(incomingMessage.data || {}) };
// Configure headers using both the socket's handshake headers and the incoming message's headers
this.headers = {
host: urlObj.host,
cookie: socket.handshake.headers.cookie || undefined,
nosession: socket.handshake.headers.nosession ? true : undefined,
origin: socket.handshake.headers.origin || undefined,
...incomingMessage.headers,
};
// Assign the session from the socket's session data
this.sessionID = socket.data.sessionID;
this.session = socket.data.session;
}
}