@@ -32,28 +32,30 @@ class Server<A> extends EventEmitter<Server.Events> {
3232 */
3333 public readonly errors = new ServerErrorRegistry < A > ( ) ;
3434 private readonly server : http . Server ;
35+ private readonly port ?: number ;
3536 private readonly copyOrigin : boolean ;
3637 private readonly handleConditionalRequests : boolean ;
3738
3839 /**
3940 * Create a new HTTP server.
4041 * @param options Server options.
4142 */
42- public constructor ( options : Server . Options < A > ) {
43+ public constructor ( options ? : Server . Options < A > ) {
4344 super ( ) ;
4445 this . server = http . createServer ( {
4546 joinDuplicateHeaders : true ,
4647 } , this . listener . bind ( this ) ) ;
4748
48- this . globalHeaders = new Headers ( options . globalHeaders ) ;
49+ this . globalHeaders = new Headers ( options ? .globalHeaders ) ;
4950 if ( ! this . globalHeaders . has ( "server" ) )
5051 this . globalHeaders . set ( "Server" , `${ packageJson . name } /${ packageJson . version } ` ) ;
5152
52- this . copyOrigin = options . copyOrigin ?? false ;
53- this . handleConditionalRequests = options . handleConditionalRequests ?? true ;
54- this . _authenticators = options . authenticators ?? [ ] ;
53+ this . port = options ?. port ;
54+ this . copyOrigin = options ?. copyOrigin ?? false ;
55+ this . handleConditionalRequests = options ?. handleConditionalRequests ?? true ;
56+ this . _authenticators = options ?. authenticators ?? [ ] ;
5557
56- this . server . listen ( options . port , process . env . HOST , ( ) => this . emit ( "listening" ) ) ;
58+ if ( this . port !== undefined ) this . listen ( this . port ) . then ( ) ;
5759
5860 this . once ( "listening" , ( ) => {
5961 if ( this . listenerCount ( "error" ) === 0 )
@@ -66,20 +68,45 @@ class Server<A> extends EventEmitter<Server.Events> {
6668 return this . server . keepAliveTimeout ;
6769 }
6870
69- public async close ( ) : Promise < void > {
71+ /**
72+ * Close the server. Will stop accepting new connections and wait for existing connections to close.
73+ * @param [timeout=5000] Maximum time to wait for existing connections to close before forcibly closing them.
74+ */
75+ public async close ( timeout = 5000 ) : Promise < void > {
76+ if ( ! this . server . listening )
77+ throw new Error ( "Server is not listening." ) ;
7078 this . emit ( "closing" ) ;
79+ let timeoutId : NodeJS . Timeout ;
7180 await Promise . race ( [
7281 new Promise < void > ( resolve => {
82+ timeoutId = setTimeout ( ( ) => {
83+ this . server . closeAllConnections ( ) ;
84+ resolve ( ) ;
85+ } , timeout )
86+ } ) ,
87+ new Promise < void > ( resolve => {
88+ clearTimeout ( timeoutId ) ;
7389 this . server . close ( ( ) => resolve ( ) ) ;
7490 } ) ,
75- new Promise < void > ( resolve => setTimeout ( ( ) => {
76- this . server . closeAllConnections ( ) ;
77- resolve ( ) ;
78- } , 5000 ) ) ,
7991 ] ) ;
8092 this . emit ( "closed" ) ;
8193 }
8294
95+ /**
96+ * Start listening for connections.
97+ * @param port The HTTP listener port. From 1 to 65535. Ports 1–1023 require privileges.
98+ */
99+ public listen ( port : number ) : Promise < void > {
100+ if ( this . server . listening )
101+ throw new Error ( "Server is already listening." ) ;
102+ return new Promise ( resolve => {
103+ this . server . listen ( port , process . env . HOST , ( ) => {
104+ this . emit ( "listening" , port , process . env . HOST ) ;
105+ resolve ( ) ;
106+ } ) ;
107+ } ) ;
108+ }
109+
83110 private async listener ( req : http . IncomingMessage , res : http . ServerResponse ) {
84111 let apiRequest : Request < A > ;
85112 try {
@@ -182,9 +209,9 @@ namespace Server {
182209 export interface Options < A > {
183210 /**
184211 * The HTTP listener port. From 1 to 65535. Ports 1–1023 require
185- * privileges.
212+ * privileges. If not set, { @link Server#listen|Server.listen()} must be called manually.
186213 */
187- readonly port : number ;
214+ readonly port ? : number ;
188215
189216 /**
190217 * Headers to send with every response.
@@ -219,7 +246,7 @@ namespace Server {
219246 /**
220247 * Server is listening and ready to accept connections.
221248 */
222- listening : [ void ] ;
249+ listening : [ port : number , host ?: string ] ;
223250
224251 /**
225252 * The server is closing and not accepting new connections.
0 commit comments