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.
 
 
 

114 lines
3.2 KiB

"use strict";
const sockjs = require("sockjs");
const BaseServer = require("./BaseServer");
/** @typedef {import("../Server").WebSocketServerConfiguration} WebSocketServerConfiguration */
/** @typedef {import("../Server").ClientConnection} ClientConnection */
// Workaround for sockjs@~0.3.19
// sockjs will remove Origin header, however Origin header is required for checking host.
// See https://github.com/webpack/webpack-dev-server/issues/1604 for more information
{
// @ts-ignore
const SockjsSession = require("sockjs/lib/transport").Session;
const decorateConnection = SockjsSession.prototype.decorateConnection;
/**
* @param {import("http").IncomingMessage} req
*/
// eslint-disable-next-line func-names
SockjsSession.prototype.decorateConnection = function (req) {
decorateConnection.call(this, req);
const connection = this.connection;
if (
connection.headers &&
!("origin" in connection.headers) &&
"origin" in req.headers
) {
connection.headers.origin = req.headers.origin;
}
};
}
module.exports = class SockJSServer extends BaseServer {
// options has: error (function), debug (function), server (http/s server), path (string)
/**
* @param {import("../Server")} server
*/
constructor(server) {
super(server);
this.implementation = sockjs.createServer({
// Use provided up-to-date sockjs-client
sockjs_url: "/__webpack_dev_server__/sockjs.bundle.js",
// Default logger is very annoy. Limit useless logs.
/**
* @param {string} severity
* @param {string} line
*/
log: (severity, line) => {
if (severity === "error") {
this.server.logger.error(line);
} else if (severity === "info") {
this.server.logger.log(line);
} else {
this.server.logger.debug(line);
}
},
});
/**
* @param {import("sockjs").ServerOptions & { path?: string }} options
* @returns {string | undefined}
*/
const getPrefix = (options) => {
if (typeof options.prefix !== "undefined") {
return options.prefix;
}
return options.path;
};
const options = {
.../** @type {WebSocketServerConfiguration} */
(this.server.options.webSocketServer).options,
prefix: getPrefix(
/** @type {NonNullable<WebSocketServerConfiguration["options"]>} */
(
/** @type {WebSocketServerConfiguration} */
(this.server.options.webSocketServer).options
)
),
};
this.implementation.installHandlers(
/** @type {import("http").Server} */ (this.server.server),
options
);
this.implementation.on("connection", (client) => {
// @ts-ignore
// Implement the the same API as for `ws`
client.send = client.write;
// @ts-ignore
client.terminate = client.close;
this.clients.push(/** @type {ClientConnection} */ (client));
client.on("close", () => {
this.clients.splice(
this.clients.indexOf(/** @type {ClientConnection} */ (client)),
1
);
});
});
// @ts-ignore
this.implementation.close = (callback) => {
callback();
};
}
};