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.
- ES Module
- CommonJS
/*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
});
/*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.*/
const { ZilaServer, ZilaClient, WebSocketClient, IncomingHttpHeaders } = require("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"; //--> true
socket.clientData.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.
- ES Module
- CommonJS
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";
}
});
const { IServerSettings, ZilaClient, ZilaServer, ZilaWSCallback } = require("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";
}
});