ziron-server
Version:
203 lines (202 loc) • 8.71 kB
TypeScript
import ServerOptions from "./ServerOptions";
import { OriginsChecker } from "./OriginsChecker";
import AuthEngine from "./AuthEngine";
import Socket from "./Socket";
import EventEmitter from "emitix";
import ChannelExchange from "./ChannelExchange";
import InternalBroker from "./broker/InternalBroker";
import { HttpResponse } from "./http/EnhanceHttpResponse";
import UpgradeRequest from "./http/UpgradeRequest";
import { BatchOption, ComplexTypesOption } from "ziron-engine";
import { SkipGroupMemberOption } from "./Options";
import { HttpRequest } from "./http/EnhanceHttpRequest";
type LocalEvents<S extends Socket> = {
'error': [Error];
'warning': [Error];
'badSocketAuthToken': [S, Error, string];
'disconnection': [S, number, any];
};
type UpgradeMiddleware = (req: UpgradeRequest) => Promise<void> | void;
type SocketMiddleware<S extends Socket> = (socket: S) => Promise<void> | void;
type AuthenticateMiddleware<S extends Socket> = (socket: S, authToken: object, signedAuthToken: string) => Promise<void> | void;
type SubscribeMiddleware<S extends Socket> = (socket: S, channel: string) => Promise<void> | void;
type PublishInMiddleware<S extends Socket> = (socket: S, channel: string, data: any) => Promise<void> | void;
/**
* @description
* The Ziron server.
* Mostly everything is related to web socket protocol on the server instance.
* But an HTTP/HTTPS server is created to catch upgrade requests and to create a health endpoint.
* All other HTTP requests will be answered with 426 (Upgrade Required),
* but it is possible to provide a custom HTTP request handler.
*/
export default class Server<E extends {
[key: string]: any[];
} = {}, ES extends Socket = Socket> {
private readonly _compressionOptions;
readonly originsChecker: OriginsChecker;
readonly auth: AuthEngine;
get id(): string;
get port(): number;
get path(): string;
get tls(): boolean;
private _authTokenExpireCheckerTicker;
private _pingTicker;
private _listenToken?;
private _startListenPromise?;
private readonly _groupTransport;
protected emitter: (EventEmitter<LocalEvents<ES>> & EventEmitter<E>);
readonly once: (EventEmitter<LocalEvents<ES>> & EventEmitter<E>)['once'];
readonly on: (EventEmitter<LocalEvents<ES>> & EventEmitter<E>)['on'];
readonly off: (EventEmitter<LocalEvents<ES>> & EventEmitter<E>)['off'];
/**
* @description
* The connected web socket clients count.
*/
readonly clientCount: number;
/**
* @description
* The connected web socket clients.
*/
readonly clients: Record<string, ES>;
/**
* @description
* This is a counter of WebSocket messages.
* You can reset this counter with the resetWsMessageCount method.
*/
readonly wsMessageCount: number;
/**
* @description
* This is a counter of received invoke messages.
* You can reset this counter with the resetInvokeMessageCount method.
*/
readonly invokeMessageCount: number;
/**
* @description
* This is a counter of received transmit messages.
* You can reset this counter with the resetTransmitMessageCount method.
*/
readonly transmitMessageCount: number;
/**
* @description
* This is a counter of HTTP messages.
* You can reset this counter with the resetHttpMessageCount method.
*/
readonly httpMessageCount: number;
/**
* @description
* Specify a socket constructor extension.
* This extension will be called in the socket constructor and
* can be used to add properties to the Socket instance.
* Use this extension only when you know what you are doing.
* It is also recommended specifying this new Socket type at the
* generic ES (extended socket) parameter of the Server class.
* This approach is implemented rather than a custom Socket class to prevent
* a larger proto chain and for the ability to add external variables into the constructor easily.
*/
socketConstructorExtension: (socket: Socket) => void;
/**
* @description
* The connection handler will be called when a new socket is connected.
* The handler can be used to register receivers or procedures on the socket.
* The returned value will be transmitted to the client.
* Promises are considered, and the connection is only ready when the promise is resolved.
*/
connectionHandler: (socket: ES) => Promise<any> | any;
/**
* @description
* Set this property to handle HTTP requests.
* Notice that firstly Ziron checks the origin and catches and processes health endpoint requests.
* The handler will be called when the request is not answered after the Ziron pipeline.
* If the response is still available after the Ziron pipeline and
* the handler call Ziron responds with a 426 (Upgrade Required) response.
*/
httpRequestHandler?: (req: HttpRequest, res: HttpResponse) => Promise<any> | any;
/**
* @description
* Specify a custom health check.
* This health check is used to process the value for the health endpoint.
* This endpoint could be used for docker health checks.
*/
healthCheck: () => Promise<boolean> | boolean;
upgradeMiddleware: UpgradeMiddleware | undefined;
socketMiddleware: SocketMiddleware<ES> | undefined;
authenticateMiddleware: AuthenticateMiddleware<ES> | undefined;
subscribeMiddleware: SubscribeMiddleware<ES> | undefined;
publishInMiddleware: PublishInMiddleware<ES> | undefined;
protected readonly internalBroker: InternalBroker;
readonly channels: ChannelExchange;
/**
* @description
* Boolean that indicates if the server should reject web socket handshakes.
*/
refuseConnections: boolean;
ignoreFurtherTransmits: boolean;
ignoreFurtherInvokes: boolean;
constructor(options?: ServerOptions);
private _createGroupTransport;
private _createTransportOptions;
private _loadCompressionOptions;
private _setUpSocketChLimit;
private _setUpApp;
private _startPingInterval;
private _startAuthExpireCheck;
private static _abortUpgrade;
private _handleUpgrade;
private _handleWsOpen;
private _handleWsMessage;
private static _handleWsDrain;
private static _handleWsClose;
private _setupHttpRequestHandling;
private _processHttpHealthCheckRequest;
/**
* @description
* Sends a transmit to a group.
* Instead of channels, groups can only be accessed and controlled from the server-side and
* messages are not shared across multiple server instances.
* Groups don't have their own special protocol and can be used to send a standard
* transmit optimized to multiple sockets of a group.
* Additionally, the group transmits support batching when not using the skipMember option.
* When using the skipMember option, the batch option will be ignored.
* Internally prepareMultiTransmit is used to create the transmit packet,
* so binary data is supported.
* @param group
* @param receiver
* @param data
* @param options
*/
transmitToGroup(group: string, receiver: string, data?: any, options?: ComplexTypesOption & BatchOption & SkipGroupMemberOption): void;
/**
* @description
* Returns the member count of a specific group from this server instance.
* Instead of channels, groups can only be accessed and controlled from the server-side and
* messages are not shared across multiple server instances.
* Groups don't have their own special protocol and can be used to send a standard
* transmit optimized to multiple sockets of a group.
* Additionally, the group transmits support batching when not using the skipMember option.
* Internally prepareMultiTransmit is used to create the transmit packet,
* so binary data is supported.
* @param group
*/
getGroupMemberCount(group: string): number;
listen(): Promise<void>;
getInternalSubscriptions(): string[];
resetWsMessageCount(): void;
resetInvokeMessageCount(): void;
resetTransmitMessageCount(): void;
resetHttpMessageCount(): void;
/**
* @description
* Resets all counts (wsMessageCount,invokeMessageCount,transmitMessageCount and httpMessageCount).
*/
resetCounts(): void;
stopListen(): void;
isListening(): boolean;
/**
* Terminates the server.
* After termination, you should not use this instance anymore
* or anything else from the server.
* [Use this method only when you know what you do.]
*/
terminate(): void;
}
export {};