UNPKG

19.4 kBSource Map (JSON)View Raw
1{"version":3,"file":"Server.js","sourceRoot":"","sources":["../../../src/lib/Server.ts"],"names":[],"mappings":"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","sourcesContent":["import { json, urlencoded } from 'body-parser';\nimport * as express from 'express';\nimport { Server as HttpServer } from 'http';\nimport { Socket } from 'net';\nimport * as WebSocket from 'ws';\nimport { Handle } from '@theintern/common';\n\nimport { pullFromArray } from './common/util';\nimport { isErrnoException } from './node/util';\nimport Node from './executors/Node';\nimport { Message } from './channels/Base';\n\nimport instrument from './middleware/instrument';\nimport unhandled from './middleware/unhandled';\nimport finalError from './middleware/finalError';\nimport resolveSuites from './middleware/resolveSuites';\nimport post from './middleware/post';\nimport filterUrl from './middleware/filterUrl';\n\nexport interface Context {\n readonly stopped: boolean;\n readonly basePath: string;\n readonly executor: Node;\n handleMessage(message: Message): Promise<any>;\n}\n\nexport default class Server implements ServerProperties {\n /** Executor managing this Server */\n readonly executor!: Node;\n\n /** Base path to resolve file requests against */\n basePath!: string;\n\n /** Port to use for HTTP connections */\n port!: number;\n\n /**\n * If true, wait for emit handlers to complete before responding to a\n * message\n */\n runInSync!: boolean;\n\n /** Port to use for WebSocket connections */\n socketPort!: number;\n\n get stopped() {\n return !this._httpServer;\n }\n\n protected _app: express.Express | undefined;\n protected _httpServer: HttpServer | undefined;\n protected _sessions:\n | { [id: string]: { listeners: ServerListener[] } }\n | undefined;\n protected _wsServer: WebSocket.Server | undefined;\n\n constructor(options: ServerOptions) {\n Object.assign(\n this,\n {\n basePath: '.',\n runInSync: false\n },\n options\n );\n }\n\n start() {\n let startupError: Error;\n let wsServer: WebSocket.Server;\n let httpServer: HttpServer;\n\n return new Promise<void>((resolve, reject) => {\n const app = (this._app = express());\n this._sessions = {};\n\n this.executor.log(\n 'Listening for WebSocket connections on port',\n this.socketPort\n );\n\n wsServer = new WebSocket.Server({ port: this.socketPort });\n wsServer.on('connection', client => {\n this.executor.log('WebSocket connection opened:', client);\n this._handleWebSocket(client);\n });\n wsServer.on('error', error => {\n if (isErrnoException(error) && error.code === 'EADDRINUSE') {\n const err: NodeJS.ErrnoException = new Error(\n `Something is already listening on the websocket server port (${\n this.socketPort\n })`\n );\n err.code = error.code;\n err.errno = error.errno;\n reject(err);\n } else if (!this._wsServer) {\n reject(error);\n } else {\n this.executor.emit('error', error);\n }\n });\n\n const context = Object.create(null, {\n stopped: {\n enumerable: true,\n get: () => this.stopped\n },\n basePath: {\n enumerable: true,\n get: () => this.basePath\n },\n executor: {\n enumerable: true,\n get: () => this.executor\n },\n handleMessage: {\n enumerable: false,\n writable: false,\n configurable: false,\n value: (message: Message) => this._handleMessage(message)\n }\n });\n\n // Add \"intern\" object to both request and response objects\n Object.defineProperty(app.request, 'intern', {\n enumerable: true,\n get: () => context\n });\n Object.defineProperty(app.response, 'intern', {\n enumerable: true,\n get: () => context\n });\n\n app.use(filterUrl());\n\n // Handle JSON and form-encoded request bodies\n app.use(json({ limit: '1mb' }), urlencoded({ extended: true }));\n\n // Log all requests\n app.use((request, _response, next) => {\n this.executor.log(`${request.method} request for ${request.url}`);\n return next();\n });\n\n const internPath = this.executor.config.internPath;\n\n // Allow resolution using both __intern and node_modules/intern.\n // Note that internPath will always end with a '/'.\n app.use(\n [`/${internPath}__resolveSuites__`, '/__intern/__resolveSuites__'],\n resolveSuites(context)\n );\n\n // Map __intern to config.internPath\n app.use('/__intern', express.static(internPath, { fallthrough: false }));\n\n // TODO: Allow user to add middleware here\n\n app.use(\n instrument(context),\n express.static(this.basePath),\n post(context),\n unhandled(),\n finalError()\n );\n\n httpServer = app.listen(this.port, resolve);\n httpServer.on('error', error => {\n if (isErrnoException(error) && error.code === 'EADDRINUSE') {\n const err: NodeJS.ErrnoException = new Error(\n `Something is already listening on the server port (${this.port})`\n );\n err.code = error.code;\n err.errno = error.errno;\n reject(err);\n } else if (!this._httpServer) {\n reject(error);\n } else {\n this.executor.emit('error', error);\n }\n });\n\n const sockets: Socket[] = [];\n\n // If sockets are not manually destroyed then Node.js will keep\n // itself running until they all expire\n httpServer.on('close', () => {\n let socket: Socket | undefined;\n while ((socket = sockets.pop())) {\n socket.destroy();\n }\n });\n\n httpServer.on('connection', socket => {\n sockets.push(socket);\n this.executor.log(\n 'HTTP connection opened,',\n sockets.length,\n 'open connections'\n );\n\n socket.on('close', () => {\n let index = sockets.indexOf(socket);\n index !== -1 && sockets.splice(index, 1);\n this.executor.log(\n 'HTTP connection closed,',\n sockets.length,\n 'open connections'\n );\n });\n });\n })\n .then(() => {\n this._wsServer = wsServer;\n this._httpServer = httpServer;\n })\n .catch(error => {\n startupError = error;\n try {\n wsServer.close();\n } catch (_error) {}\n try {\n httpServer.close();\n } catch (_error) {}\n })\n .then(() => {\n if (startupError) {\n throw startupError;\n }\n });\n }\n\n stop() {\n this.executor.log('Stopping server...');\n const promises: Promise<any>[] = [];\n\n if (this._app && this._httpServer) {\n promises.push(\n new Promise(resolve => {\n this._httpServer!.close(resolve);\n }).then(() => {\n this.executor.log('Stopped http server');\n this._app = this._httpServer = undefined;\n })\n );\n }\n\n if (this._wsServer) {\n promises.push(\n new Promise(resolve => {\n this._wsServer!.close(resolve);\n }).then(() => {\n this.executor.log('Stopped ws server');\n this._wsServer = undefined;\n })\n );\n }\n\n return Promise.all(promises);\n }\n\n /**\n * Listen for all events for a specific session\n */\n subscribe(sessionId: string, listener: ServerListener): Handle {\n const listeners = this._getSession(sessionId).listeners;\n listeners.push(listener);\n return {\n destroy: function(this: any) {\n this.destroy = function() {};\n pullFromArray(listeners, listener);\n }\n };\n }\n\n private _getSession(sessionId: string) {\n let session = this._sessions![sessionId];\n if (!session) {\n session = this._sessions![sessionId] = { listeners: [] };\n }\n return session;\n }\n\n private _handleMessage(message: Message): Promise<any> {\n this.executor.log(\n 'Processing message [',\n message.id,\n '] for ',\n message.sessionId,\n ': ',\n message.name\n );\n\n const promise = this._publish(message);\n if (getShouldWait(this.runInSync, message)) {\n return promise;\n }\n\n // If we're not returning the promise, catch any errors to avoid\n // unhandled rejections\n promise.catch(error => {\n this.executor.emit('error', error);\n });\n\n return resolvedPromise;\n }\n\n private _handleWebSocket(client: WebSocket) {\n client.on('message', data => {\n this.executor.log('Received WebSocket message');\n const message: Message = JSON.parse(data.toString());\n this._handleMessage(message)\n .catch(error => this.executor.emit('error', error))\n .then(() => {\n this.executor.log('Sending ack for [', message.id, ']');\n client.send(JSON.stringify({ id: message.id }), error => {\n if (error) {\n this.executor.emit(\n 'error',\n new Error(\n `Error sending ack for [ ${message.id} ]: ${error.message}`\n )\n );\n }\n });\n });\n });\n\n client.on('error', error => {\n this.executor.log('WebSocket client error:', error);\n this.executor.emit('error', error);\n });\n }\n\n private _publish(message: Message) {\n const listeners = this._getSession(message.sessionId).listeners;\n return Promise.all(\n listeners.map(listener => listener(message.name, message.data))\n );\n }\n}\n\nexport interface ServerProperties {\n basePath: string;\n executor: Node;\n port: number;\n runInSync: boolean;\n socketPort: number;\n}\n\nexport interface ServerListener {\n (name: string, data?: any): void;\n}\n\nexport type ServerOptions = Partial<ServerProperties> & { executor: Node };\n\nconst resolvedPromise = Promise.resolve();\n\n/**\n * Indicate whether Server should wait for an event to process before sending an\n * acknowlegement.\n */\nfunction getShouldWait(waitMode: string | boolean, message: Message) {\n let eventName = message.name;\n\n // never wait for runEnd\n if (eventName === 'runEnd') {\n return false;\n }\n\n let shouldWait = false;\n\n if (waitMode === 'fail') {\n if (\n (eventName === 'testEnd' && message.data.error) ||\n (eventName === 'suiteEnd' && message.data.error) ||\n eventName === 'error'\n ) {\n shouldWait = true;\n }\n } else if (waitMode === true) {\n shouldWait = true;\n } else if (Array.isArray(waitMode) && waitMode.indexOf(eventName) !== -1) {\n shouldWait = true;\n }\n\n return shouldWait;\n}\n"]}
\No newline at end of file