Skip to main content
Version: 2.2.x

Extending

ZilaClient

You have the ability to extend the ZilaClient class. ZilaClient is a class for storing server side data and functions of a WS connection. Extending is good for storing extra data (or even declaring functions) associated with a client thus making it the best way to handle authentication.

/*You should not use the WebSocketClient constructor since it's a part of the `ws` npm package,
and is only exported to make the extending easier.*/
import { ZilaServer, ZilaClient, WebSocketClient, IncomingHttpHeaders } from "zilaws-server";

interface IClientData {
rank: "admin" | "user";
username: string;
}

class MyClient extends ZilaClient {
public clientData?: IClientData;

//Sadly, you need to define the constructor by hand.
constructor(
socket: WebSocketClient,
ip: string | undefined,
server: ZilaServer,
isBrowser: boolean,
headers: IncomingHttpHeaders,
cookies?: Map<string, string>
) {
super(socket, ip, server, isBrowser, headers, cookies);

//This is the best place to authenticate the user.
if(isBrowser && !AuthUserByBrowser(cookies?.get("loginToken"))) {
this.kick("Wrong token");
return;
}else if (!AuthUserByHeader(headers["authorization"])) {
this.kick("Wrong token");
return;
}

this.clientData = {
rank: "admin",
username: "SomeUsername"
}
}
}

//Defining both the generic type and the clientClass is needed.
const server = new ZilaServer<MyClient>({
port: 6589,
logger: true,
verbose: true,
clientClass: MyClient
});

server.onceMessageHandler("Anything", (socket) => {
socket.clientData == {
rank: "admin",
username: "SomeUsername"
}; //--> true
});

ZilaServer

You also have the ability to extend the ZilaServer class if you need to. This comes in handy if for example you need to convert data automatically.

import { IServerSettings, ZilaClient, ZilaServer, ZilaWSCallback } from "zilaws-server";

enum MessageHandlers {
Register,
Login,
//...
}

class MyServer<T extends ZilaClient> extends ZilaServer<T> {
constructor(settings: IServerSettings) {
super(settings);
}

setMessageHandler(identifier: MessageHandlers | string, callback: ZilaWSCallback<T>): void {
super.setMessageHandler(identifier.toString(), callback);
}
}

const server = new MyServer<MyClient>({
port: 80,
clientClass: MyClient
});

server.setMessageHandler(MessageHandlers.Login, async (socket: MyClient, username: string, password: string) => {
//Logging in a user
const dbUser = await CheckLoginCredentials(username, password);

if(dbUser) {
const loginToken = generateToken();
socket.setCookie({
name: "LoginToken",
value: loginToken,
expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 30)
});

socket.clientData = dbUser;

return "SUCCESS";
}else{
return "BAD_CREDENTIALS";
}
});