You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
3.5 KiB

'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. */