WebsocketServer.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _ws = require("ws");
  7. var _BaseServer = _interopRequireDefault(require("./BaseServer.js"));
  8. function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
  9. /** @typedef {import("../Server.js").WebSocketServerConfiguration} WebSocketServerConfiguration */
  10. /** @typedef {import("../Server.js").ClientConnection} ClientConnection */
  11. class WebsocketServer extends _BaseServer.default {
  12. static heartbeatInterval = 1000;
  13. /**
  14. * @param {import("../Server.js").default} server server
  15. */
  16. constructor(server) {
  17. super(server);
  18. /** @type {import("ws").ServerOptions} */
  19. const options = {
  20. ... /** @type {WebSocketServerConfiguration} */
  21. this.server.options.webSocketServer.options,
  22. clientTracking: false
  23. };
  24. const isNoServerMode = typeof options.port === "undefined" && typeof options.server === "undefined";
  25. if (isNoServerMode) {
  26. options.noServer = true;
  27. }
  28. this.implementation = new _ws.WebSocketServer(options);
  29. /** @type {import("http").Server} */
  30. this.server.server.on("upgrade",
  31. /**
  32. * @param {import("http").IncomingMessage} req request
  33. * @param {import("stream").Duplex} sock socket
  34. * @param {Buffer} head head
  35. */
  36. (req, sock, head) => {
  37. if (!this.implementation.shouldHandle(req)) {
  38. return;
  39. }
  40. this.implementation.handleUpgrade(req, sock, head, connection => {
  41. this.implementation.emit("connection", connection, req);
  42. });
  43. });
  44. this.implementation.on("error",
  45. /**
  46. * @param {Error} err error
  47. */
  48. err => {
  49. this.server.logger.error(err.message);
  50. });
  51. const interval = setInterval(() => {
  52. for (const client of this.clients) {
  53. if (client.isAlive === false) {
  54. client.terminate();
  55. continue;
  56. }
  57. client.isAlive = false;
  58. client.ping(() => {});
  59. }
  60. }, WebsocketServer.heartbeatInterval);
  61. this.implementation.on("connection",
  62. /**
  63. * @param {ClientConnection} client client
  64. */
  65. client => {
  66. this.clients.push(client);
  67. client.isAlive = true;
  68. client.on("pong", () => {
  69. client.isAlive = true;
  70. });
  71. client.on("close", () => {
  72. this.clients.splice(this.clients.indexOf(client), 1);
  73. });
  74. // TODO: add a test case for this - https://github.com/webpack/webpack-dev-server/issues/5018
  75. client.on("error",
  76. /**
  77. * @param {Error} err err
  78. */
  79. err => {
  80. this.server.logger.error(err.message);
  81. });
  82. });
  83. this.implementation.on("close", () => {
  84. clearInterval(interval);
  85. });
  86. }
  87. }
  88. exports.default = WebsocketServer;