110 lines
3.5 KiB
JavaScript
110 lines
3.5 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = expressWs;
|
|
|
|
var _http = require('http');
|
|
|
|
var _http2 = _interopRequireDefault(_http);
|
|
|
|
var _express = require('express');
|
|
|
|
var _express2 = _interopRequireDefault(_express);
|
|
|
|
var _ws = require('ws');
|
|
|
|
var _ws2 = _interopRequireDefault(_ws);
|
|
|
|
var _websocketUrl = require('./websocket-url');
|
|
|
|
var _websocketUrl2 = _interopRequireDefault(_websocketUrl);
|
|
|
|
var _addWsMethod = require('./add-ws-method');
|
|
|
|
var _addWsMethod2 = _interopRequireDefault(_addWsMethod);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
function expressWs(app, httpServer) {
|
|
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
|
|
var server = httpServer;
|
|
|
|
if (server === null || server === undefined) {
|
|
/* No HTTP server was explicitly provided, create one for our Express application. */
|
|
server = _http2.default.createServer(app);
|
|
|
|
app.listen = function serverListen() {
|
|
var _server;
|
|
|
|
return (_server = server).listen.apply(_server, arguments);
|
|
};
|
|
}
|
|
|
|
/* Make our custom `.ws` method available directly on the Express application. You should
|
|
* really be using Routers, though. */
|
|
(0, _addWsMethod2.default)(app);
|
|
|
|
/* Monkeypatch our custom `.ws` method into Express' Router prototype. This makes it possible,
|
|
* when using the standard Express Router, to use the `.ws` method without any further calls
|
|
* to `makeRouter`. When using a custom router, the use of `makeRouter` may still be necessary.
|
|
*
|
|
* This approach works, because Express does a strange mixin hack - the Router factory
|
|
* function is simultaneously the prototype that gets assigned to the resulting Router
|
|
* object. */
|
|
if (!options.leaveRouterUntouched) {
|
|
(0, _addWsMethod2.default)(_express2.default.Router);
|
|
}
|
|
|
|
// allow caller to pass in options to WebSocketServer constructor
|
|
var wsOptions = options.wsOptions || {};
|
|
wsOptions.server = server;
|
|
var wsServer = new _ws2.default.Server(wsOptions);
|
|
|
|
wsServer.on('connection', function (socket, request) {
|
|
if ('upgradeReq' in socket) {
|
|
request = socket.upgradeReq;
|
|
}
|
|
|
|
request.ws = socket;
|
|
request.wsHandled = false;
|
|
|
|
/* By setting this fake `.url` on the request, we ensure that it will end up in the fake
|
|
* `.get` handler that we defined above - where the wrapper will then unpack the `.ws`
|
|
* property, indicate that the WebSocket has been handled, and call the actual handler. */
|
|
request.url = (0, _websocketUrl2.default)(request.url);
|
|
|
|
var dummyResponse = new _http2.default.ServerResponse(request);
|
|
|
|
dummyResponse.writeHead = function writeHead(statusCode) {
|
|
if (statusCode > 200) {
|
|
/* Something in the middleware chain signalled an error. */
|
|
dummyResponse._header = '';
|
|
socket.close();
|
|
}
|
|
};
|
|
|
|
app.handle(request, dummyResponse, function () {
|
|
if (!request.wsHandled) {
|
|
/* There was no matching WebSocket-specific route for this request. We'll close
|
|
* the connection, as no endpoint was able to handle the request anyway... */
|
|
socket.close();
|
|
}
|
|
});
|
|
});
|
|
|
|
return {
|
|
app: app,
|
|
getWss: function getWss() {
|
|
return wsServer;
|
|
},
|
|
applyTo: function applyTo(router) {
|
|
(0, _addWsMethod2.default)(router);
|
|
}
|
|
};
|
|
} /* This module does a lot of monkeypatching, but unfortunately that appears to be the only way to
|
|
* accomplish this kind of stuff in Express.
|
|
*
|
|
* Here be dragons. */ |