diff --git a/src/server.ts b/src/server.ts index 0ee2db8..2a226d5 100644 --- a/src/server.ts +++ b/src/server.ts @@ -22,16 +22,24 @@ export interface WebSocketServer extends EventEmitter { class Server extends EventEmitter { private readonly server: http.Server | https.Server + private readonly wsServer: WSServer - constructor (server: http.Server | https.Server) { + constructor (server: http.Server | https.Server, opts?: ServerOptions) { super() - + opts = opts ?? {} this.server = server + this.wsServer = new WSServer({ + server: server, + perMessageDeflate: false, + verifyClient: opts.verifyClient + }) + this.wsServer.on('connection', this.onWsServerConnection.bind(this)) } async listen (addrInfo: { port: number } | number) { - return await new Promise(resolve => { - this.once('listening', () => resolve(this)) + return await new Promise((resolve, reject) => { + this.wsServer.once('error', (e) => reject(e)) + this.wsServer.once('listening', () => resolve(this)) this.server.listen(typeof addrInfo === 'number' ? addrInfo : addrInfo.port) }) } @@ -51,6 +59,31 @@ class Server extends EventEmitter { address () { return this.server.address() } + + onWsServerConnection (socket: WebSocket, req: http.IncomingMessage) { + const addr = this.wsServer.address() + + if (typeof addr === 'string') { + this.emit('error', new Error('Cannot listen on unix sockets')) + return + } + + if (req.socket.remoteAddress == null || req.socket.remotePort == null) { + this.emit('error', new Error('Remote connection did not have address and/or port')) + return + } + + const stream: DuplexWebSocket = { + ...duplex(socket, { + remoteAddress: req.socket.remoteAddress, + remotePort: req.socket.remotePort + }), + localAddress: addr.address, + localPort: addr.port + } + + this.emit('connection', stream, req) + } } export function createServer (opts?: ServerOptions): WebSocketServer { @@ -69,40 +102,9 @@ export function createServer (opts?: ServerOptions): WebSocketServer { }) } - const wsServer = new WSServer({ - server: server, - perMessageDeflate: false, - verifyClient: opts.verifyClient - }) - proxy(server, 'listening') proxy(server, 'request') proxy(server, 'close') - wsServer.on('connection', function (socket: WebSocket, req: http.IncomingMessage) { - const addr = wsServer.address() - - if (typeof addr === 'string') { - wss.emit('error', new Error('Cannot listen on unix sockets')) - return - } - - if (req.socket.remoteAddress == null || req.socket.remotePort == null) { - wss.emit('error', new Error('Remote connection did not have address and/or port')) - return - } - - const stream: DuplexWebSocket = { - ...duplex(socket, { - remoteAddress: req.socket.remoteAddress, - remotePort: req.socket.remotePort - }), - localAddress: addr.address, - localPort: addr.port - } - - wss.emit('connection', stream, req) - }) - return wss } diff --git a/test/server-address.spec.ts b/test/server-address.spec.ts index 0c0b39c..c55cd4e 100644 --- a/test/server-address.spec.ts +++ b/test/server-address.spec.ts @@ -14,4 +14,12 @@ describe('address', () => { expect(server.address()).to.have.property('port', 55214, 'return address should match') await server.close() }) + + it('server listen error should be catchable', async () => { + const server1 = WS.createServer() + await server1.listen(55215) + const server2 = WS.createServer() + await expect(server2.listen(55215)).to.be.eventually.rejectedWith('listen EADDRINUSE') + await server1.close() + }) })