1
1
import * as express from "express"
2
2
import * as http from "http"
3
+ import * as net from "net"
3
4
import * as nodeFetch from "node-fetch"
4
5
import Websocket from "ws"
5
6
import * as util from "../src/common/util"
@@ -8,13 +9,21 @@ import { handleUpgrade } from "../src/node/wsRouter"
8
9
9
10
// Perhaps an abstraction similar to this should be used in app.ts as well.
10
11
export class HttpServer {
11
- private hs = http . createServer ( )
12
+ private readonly sockets = new Set < net . Socket > ( )
13
+ private cleanupTimeout ?: NodeJS . Timeout
12
14
13
- public constructor ( hs ?: http . Server ) {
14
- // See usage in test/integration.ts
15
- if ( hs ) {
16
- this . hs = hs
17
- }
15
+ // See usage in test/integration.ts
16
+ public constructor ( private readonly hs = http . createServer ( ) ) {
17
+ this . hs . on ( "connection" , ( socket ) => {
18
+ this . sockets . add ( socket )
19
+ socket . on ( "close" , ( ) => {
20
+ this . sockets . delete ( socket )
21
+ if ( this . cleanupTimeout && this . sockets . size === 0 ) {
22
+ clearTimeout ( this . cleanupTimeout )
23
+ this . cleanupTimeout = undefined
24
+ }
25
+ } )
26
+ } )
18
27
}
19
28
20
29
/**
@@ -54,13 +63,28 @@ export class HttpServer {
54
63
*/
55
64
public close ( ) : Promise < void > {
56
65
return new Promise ( ( res , rej ) => {
66
+ // Close will not actually close anything; it just waits until everything
67
+ // is closed.
57
68
this . hs . close ( ( err ) => {
58
69
if ( err ) {
59
70
rej ( err )
60
71
return
61
72
}
62
73
res ( )
63
74
} )
75
+
76
+ // If there are sockets remaining we might need to force close them or
77
+ // this promise might never resolve.
78
+ if ( this . sockets . size > 0 ) {
79
+ // Give sockets a chance to close up shop.
80
+ this . cleanupTimeout = setTimeout ( ( ) => {
81
+ this . cleanupTimeout = undefined
82
+ for ( const socket of this . sockets . values ( ) ) {
83
+ console . warn ( "a socket was left hanging" )
84
+ socket . destroy ( )
85
+ }
86
+ } , 1000 )
87
+ }
64
88
} )
65
89
}
66
90
0 commit comments