import * as http from "http" ; import * as https from "https" ; import ConfigurationBase from "./ConfigurationBase" ; import ICleaner from "./ICleaner" ; import IRequestListenerFactory from "./IRequestListenerFactory" ; export type RequestListener = ( request : http . IncomingMessage , response : http . ServerResponse ) => void ; export enum ServerStatus { Closed = "Closed" , Starting = "Starting" , Running = "Running" , Closing = "Closing" } export abstract class export default abstract class ServerBase implements ICleaner { protected status : ServerStatus = ServerStatus . Closed ; param { string } host param { number } port param { http . Server | https . Server } httpServer param { IRequestListenerFactory } requestListenerFactory memberof public constructor ( public readonly host , public readonly port , public readonly httpServer , requestListenerFactory , public readonly config ) { this . httpServer . removeAllListeners ( "request" ) ; this . httpServer . on ( "request" , requestListenerFactory . createRequestListener ( ) ) ; } returns { string } memberof public getHttpServerAddress ( ) { const address = this . httpServer . address ( ) ; const protocol = `http${ this . config . hasCert ( ) ? "s" : "" }://` ; if ( typeof address === "string" ) { return protocol + address ; } else if ( address === null ) { return "" ; } else { return `${ protocol }${ address . address }:${ address . port }` ; } } public getStatus ( ) { return this . status ; } abstract returns { Promise < void > } memberof public async start ( ) { if ( this . status !== ServerStatus . Closed ) { throw Error ( `Cannot start server in status ${ ServerStatus [ this . status ] }` ) ; } this . status = ServerStatus . Starting ; try { await this . beforeStart ( ) ; await new Promise < void > ( ( resolve , reject ) => { this . httpServer . listen ( this . port , this . host , resolve ) . on ( "error" , reject ) ; } ) ; this . status = ServerStatus . Running ; } catch ( err ) { this . status = ServerStatus . Closed ; throw err ; } await this . afterStart ( ) ; } abstract returns { Promise < void > } memberof public async close ( ) { if ( this . status !== ServerStatus . Running ) { throw Error ( `Cannot close server in status ${ ServerStatus [ this . status ] }` ) ; } this . status = ServerStatus . Closing ; await this . beforeClose ( ) ; this . httpServer . removeAllListeners ( "request" ) ; await new Promise ( resolve => { this . httpServer . close ( resolve ) ; } ) ; await this . afterClose ( ) ; this . status = ServerStatus . Closed ; } public async clean ( ) { } protected abstract returns { Promise < void > } memberof protected async beforeStart ( ) { } protected abstract returns { Promise < void > } memberof protected async afterStart ( ) { } protected abstract returns { Promise < void > } memberof protected async beforeClose ( ) { } protected abstract returns { Promise < void > } memberof protected async afterClose ( ) { } }