@freemework/hosting
Version:
Hosting library of the Freemework Project.
187 lines (186 loc) • 9.55 kB
TypeScript
import { FDisposable, FExecutionContext, type FChannelPublisher, type FChannelSubscriber, FCancellationToken, FInitableBase, FLogger } from "@freemework/common";
import express from 'express';
import http from "http";
import https from "https";
import WebSocket from "ws";
import { FHostingSettings } from "./f_hosting_settings.js";
export { FHostingSettings, FHostingConfiguration } from "./f_hosting_settings.js";
export { FHttpRequestCancellationToken } from "./FHttpRequestCancellationToken.js";
export * from "./configuration/index.js";
export * from "./launcher/index.js";
export type FWebServerRequestHandler = http.RequestListener;
export interface FWebServer extends FInitableBase {
readonly name: string;
readonly underlyingServer: http.Server | https.Server;
rootExpressApplication: express.Application;
bindRequestHandler(bindPath: string, handler: FWebServerRequestHandler): void;
createWebSocketServer(bindPath: string): WebSocket.Server;
destroyWebSocketServer(bindPath: string): Promise<void>;
}
export declare abstract class FAbstractWebServer<TOpts extends FHostingSettings.WebServerBase | FHostingSettings.WebServer> extends FInitableBase implements FWebServer {
abstract readonly underlyingServer: http.Server | https.Server;
protected readonly _trustProxy: boolean | "loopback" | "linklocal" | "uniquelocal";
protected readonly _name: string;
protected readonly _listenHost: string;
protected readonly _listenPort: number;
protected readonly _webSockets: {
[bindPath: string]: WebSocket.Server;
};
protected readonly _log: FLogger;
protected readonly _handleUpgrade: boolean;
private readonly _onUpgrade;
private readonly _onRequestImpl;
private readonly _handlers;
private _rootExpressApplication;
static createFCancellationToken(request: http.IncomingMessage): FCancellationToken;
constructor(opts: TOpts);
/**
* Lazy create for Express Application
*/
get rootExpressApplication(): express.Application;
set rootExpressApplication(value: express.Application);
get name(): string;
bindRequestHandler(bindPath: string, value: FWebServerRequestHandler): void;
createWebSocketServer(bindPath: string): WebSocket.Server;
destroyWebSocketServer(bindPath: string): Promise<void>;
protected onInit(): Promise<void>;
protected abstract onListen(): Promise<void>;
protected onRequest(req: http.IncomingMessage, res: http.ServerResponse): void;
private onRequestCommon;
private onRequestXFCC;
private onUpgradeCommon;
private onUpgradeXFCC;
private validateXFCC;
}
export declare class UnsecuredWebServer extends FAbstractWebServer<FHostingSettings.UnsecuredWebServer> {
private readonly _httpServer;
constructor(opts: FHostingSettings.UnsecuredWebServer);
get underlyingServer(): http.Server;
protected onListen(): Promise<void>;
protected onDispose(): Promise<void>;
}
export declare class SecuredWebServer extends FAbstractWebServer<FHostingSettings.SecuredWebServer> {
private readonly _httpsServer;
constructor(opts: FHostingSettings.SecuredWebServer);
get underlyingServer(): https.Server;
protected onListen(): Promise<void>;
protected onDispose(): Promise<void>;
}
export declare abstract class FBindEndpoint extends FInitableBase {
protected readonly _bindPath: string;
constructor(opts: FHostingSettings.BindEndpoint);
protected onInit(): void | Promise<void>;
protected onDispose(): void | Promise<void>;
}
export declare abstract class FServersBindEndpoint extends FBindEndpoint {
protected readonly _servers: ReadonlyArray<FWebServer>;
constructor(servers: ReadonlyArray<FWebServer>, opts: FHostingSettings.BindEndpoint);
}
/**
* This endpoint supplies communication channels for each client connection.
*
* WebSocket Client is hosting the channel:
* - Client's messages delivered via SubscriberChannel
* - To deliver message to client use PublisherChannel
*
* If you need opposite behavior take a look for `WebSocketChannelFactoryEndpoint`
*
* You need to override onOpenBinaryChannel and/or onOpenTextChannel to obtain necessary channel
*/
export declare class FWebSocketChannelSupplyEndpoint extends FServersBindEndpoint {
private readonly _webSocketServers;
private readonly _connections;
private readonly _log;
private _defaultProtocol;
private _allowedProtocols;
private _connectionCounter;
constructor(servers: ReadonlyArray<FWebServer>, opts: FHostingSettings.WebSocketEndpoint);
protected onInit(): void;
protected onDispose(): Promise<void>;
protected onConnection(webSocket: WebSocket, request: http.IncomingMessage): void;
/**
* The method should be overridden. The method called by the endpoint,
* when WSClient sent first binary message for specified sub-protocol.
* @param webSocket WebSocket instance
* @param subProtocol These strings are used to indicate sub-protocols,
* so that a single server can implement multiple WebSocket sub-protocols (for example,
* you might want one server to be able to handle different types of interactions
* depending on the specified protocol).
* @param channel Binary channel instance to be user in inherited class
*/
protected onOpenBinaryChannel(_webSocket: WebSocket, subProtocol: string, _channel: FWebSocketChannelSupplyEndpoint.BinaryChannel): void;
/**
* The method should be overridden. The method called by the endpoint,
* when WSClient sent first text message for specified sub-protocol.
* @param webSocket WebSocket instance
* @param subProtocol These strings are used to indicate sub-protocols,
* so that a single server can implement multiple WebSocket sub-protocols (for example,
* you might want one server to be able to handle different types of interactions
* depending on the specified protocol).
* @param channel Text channel instance to be user in inherited class
*/
protected onOpenTextChannel(_webSocket: WebSocket, subProtocol: string, _channel: FWebSocketChannelSupplyEndpoint.TextChannel): void;
}
export declare namespace FWebSocketChannelSupplyEndpoint {
interface BinaryChannel extends FChannelPublisher<Uint8Array>, FChannelSubscriber<Uint8Array> {
}
interface TextChannel extends FChannelPublisher<string>, FChannelSubscriber<string> {
}
}
/**
* This endpoint requests you for communication channels for each client connection.
*
* WebSocket Client is used the channel:
* - Client's messages delivered via PublisherChannel
* - To deliver message to client use SubscriberChannel
*
* If you need opposite behavior take a look for `WebSocketChannelSupplyEndpoint`
*
* You need to override createBinaryChannel and/or createTextChannel to provide necessary channel
*/
export declare class FWebSocketChannelFactoryEndpoint extends FServersBindEndpoint {
private readonly _webSocketServers;
private readonly _connections;
private readonly _autoCreateChannelBinary;
private readonly _autoCreateChannelText;
private readonly _log;
private _defaultProtocol;
private _allowedProtocols;
private _connectionCounter;
constructor(servers: ReadonlyArray<FWebServer>, opts: FHostingSettings.WebSocketEndpoint, autoCreateChannels?: {
binary?: boolean;
text?: boolean;
});
protected onInit(): void;
protected onDispose(): Promise<void>;
protected onConnection(webSocket: WebSocket, request: http.IncomingMessage): Promise<void>;
/**
* The method should be overridden. The method called by the endpoint,
* when WSClient sent first binary message for specified sub-protocol.
* @param webSocket WebSocket instance
* @param subProtocol These strings are used to indicate sub-protocols,
* so that a single server can implement multiple WebSocket sub-protocols (for example,
* you might want one server to be able to handle different types of interactions
* depending on the specified protocol).
*/
protected createBinaryChannel(_executionContext: FExecutionContext, _webSocket: WebSocket, subProtocol: string): Promise<FWebSocketChannelFactoryEndpoint.BinaryChannel>;
/**
* The method should be overridden. The method called by the endpoint,
* when WSClient sent first text message for specified sub-protocol.
* @param webSocket WebSocket instance
* @param subProtocol These strings are used to indicate sub-protocols,
* so that a single server can implement multiple WebSocket sub-protocols (for example,
* you might want one server to be able to handle different types of interactions
* depending on the specified protocol).
*/
protected createTextChannel(_executionContext: FExecutionContext, _webSocket: WebSocket, subProtocol: string): Promise<FWebSocketChannelFactoryEndpoint.TextChannel>;
}
export declare namespace FWebSocketChannelFactoryEndpoint {
interface BinaryChannel extends FDisposable, FChannelPublisher<Uint8Array>, FChannelSubscriber<Uint8Array> {
}
interface TextChannel extends FDisposable, FChannelPublisher<string>, FChannelSubscriber<string> {
}
}
export declare function instanceofWebServer(server: any): server is FWebServer;
export declare function createWebServer(serverOpts: FHostingSettings.WebServer): FWebServer;
export declare function createWebServers(serversOpts: ReadonlyArray<FHostingSettings.WebServer>): ReadonlyArray<FWebServer>;