1 | "use strict";
|
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3 | if (k2 === undefined) k2 = k;
|
4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
5 | }) : (function(o, m, k, k2) {
|
6 | if (k2 === undefined) k2 = k;
|
7 | o[k2] = m[k];
|
8 | }));
|
9 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
10 | Object.defineProperty(o, "default", { enumerable: true, value: v });
|
11 | }) : function(o, v) {
|
12 | o["default"] = v;
|
13 | });
|
14 | var __importStar = (this && this.__importStar) || function (mod) {
|
15 | if (mod && mod.__esModule) return mod;
|
16 | var result = {};
|
17 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
18 | __setModuleDefault(result, mod);
|
19 | return result;
|
20 | };
|
21 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
22 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
23 | };
|
24 | Object.defineProperty(exports, "__esModule", { value: true });
|
25 | exports.Namespace = exports.Socket = exports.Server = void 0;
|
26 | const http = require("http");
|
27 | const fs_1 = require("fs");
|
28 | const zlib_1 = require("zlib");
|
29 | const accepts = require("accepts");
|
30 | const stream_1 = require("stream");
|
31 | const path = require("path");
|
32 | const engine_io_1 = require("engine.io");
|
33 | const client_1 = require("./client");
|
34 | const events_1 = require("events");
|
35 | const namespace_1 = require("./namespace");
|
36 | Object.defineProperty(exports, "Namespace", { enumerable: true, get: function () { return namespace_1.Namespace; } });
|
37 | const parent_namespace_1 = require("./parent-namespace");
|
38 | const socket_io_adapter_1 = require("socket.io-adapter");
|
39 | const parser = __importStar(require("socket.io-parser"));
|
40 | const debug_1 = __importDefault(require("debug"));
|
41 | const socket_1 = require("./socket");
|
42 | Object.defineProperty(exports, "Socket", { enumerable: true, get: function () { return socket_1.Socket; } });
|
43 | const typed_events_1 = require("./typed-events");
|
44 | const debug = (0, debug_1.default)("socket.io:server");
|
45 | const clientVersion = require("../package.json").version;
|
46 | const dotMapRegex = /\.map/;
|
47 | class Server extends typed_events_1.StrictEventEmitter {
|
48 | constructor(srv, opts = {}) {
|
49 | super();
|
50 | |
51 |
|
52 |
|
53 | this._nsps = new Map();
|
54 | this.parentNsps = new Map();
|
55 | if ("object" === typeof srv &&
|
56 | srv instanceof Object &&
|
57 | !srv.listen) {
|
58 | opts = srv;
|
59 | srv = undefined;
|
60 | }
|
61 | this.path(opts.path || "/socket.io");
|
62 | this.connectTimeout(opts.connectTimeout || 45000);
|
63 | this.serveClient(false !== opts.serveClient);
|
64 | this._parser = opts.parser || parser;
|
65 | this.encoder = new this._parser.Encoder();
|
66 | this.adapter(opts.adapter || socket_io_adapter_1.Adapter);
|
67 | this.sockets = this.of("/");
|
68 | this.opts = opts;
|
69 | if (srv || typeof srv == "number")
|
70 | this.attach(srv);
|
71 | }
|
72 | serveClient(v) {
|
73 | if (!arguments.length)
|
74 | return this._serveClient;
|
75 | this._serveClient = v;
|
76 | return this;
|
77 | }
|
78 | |
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 | _checkNamespace(name, auth, fn) {
|
88 | if (this.parentNsps.size === 0)
|
89 | return fn(false);
|
90 | const keysIterator = this.parentNsps.keys();
|
91 | const run = () => {
|
92 | const nextFn = keysIterator.next();
|
93 | if (nextFn.done) {
|
94 | return fn(false);
|
95 | }
|
96 | nextFn.value(name, auth, (err, allow) => {
|
97 | if (err || !allow) {
|
98 | run();
|
99 | }
|
100 | else {
|
101 | const namespace = this.parentNsps
|
102 | .get(nextFn.value)
|
103 | .createChild(name);
|
104 |
|
105 | this.sockets.emitReserved("new_namespace", namespace);
|
106 | fn(namespace);
|
107 | }
|
108 | });
|
109 | };
|
110 | run();
|
111 | }
|
112 | path(v) {
|
113 | if (!arguments.length)
|
114 | return this._path;
|
115 | this._path = v.replace(/\/$/, "");
|
116 | const escapedPath = this._path.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
|
117 | this.clientPathRegex = new RegExp("^" +
|
118 | escapedPath +
|
119 | "/socket\\.io(\\.msgpack|\\.esm)?(\\.min)?\\.js(\\.map)?(?:\\?|$)");
|
120 | return this;
|
121 | }
|
122 | connectTimeout(v) {
|
123 | if (v === undefined)
|
124 | return this._connectTimeout;
|
125 | this._connectTimeout = v;
|
126 | return this;
|
127 | }
|
128 | adapter(v) {
|
129 | if (!arguments.length)
|
130 | return this._adapter;
|
131 | this._adapter = v;
|
132 | for (const nsp of this._nsps.values()) {
|
133 | nsp._initAdapter();
|
134 | }
|
135 | return this;
|
136 | }
|
137 | |
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 | listen(srv, opts = {}) {
|
146 | return this.attach(srv, opts);
|
147 | }
|
148 | |
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 | attach(srv, opts = {}) {
|
157 | if ("function" == typeof srv) {
|
158 | const msg = "You are trying to attach socket.io to an express " +
|
159 | "request handler function. Please pass a http.Server instance.";
|
160 | throw new Error(msg);
|
161 | }
|
162 |
|
163 | if (Number(srv) == srv) {
|
164 | srv = Number(srv);
|
165 | }
|
166 | if ("number" == typeof srv) {
|
167 | debug("creating http server and binding to %d", srv);
|
168 | const port = srv;
|
169 | srv = http.createServer((req, res) => {
|
170 | res.writeHead(404);
|
171 | res.end();
|
172 | });
|
173 | srv.listen(port);
|
174 | }
|
175 |
|
176 | Object.assign(opts, this.opts);
|
177 |
|
178 | opts.path = opts.path || this._path;
|
179 | this.initEngine(srv, opts);
|
180 | return this;
|
181 | }
|
182 | |
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 | initEngine(srv, opts) {
|
190 |
|
191 | debug("creating engine.io instance with opts %j", opts);
|
192 | this.eio = (0, engine_io_1.attach)(srv, opts);
|
193 |
|
194 | if (this._serveClient)
|
195 | this.attachServe(srv);
|
196 |
|
197 | this.httpServer = srv;
|
198 |
|
199 | this.bind(this.eio);
|
200 | }
|
201 | |
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 | attachServe(srv) {
|
208 | debug("attaching client serving req handler");
|
209 | const evs = srv.listeners("request").slice(0);
|
210 | srv.removeAllListeners("request");
|
211 | srv.on("request", (req, res) => {
|
212 | if (this.clientPathRegex.test(req.url)) {
|
213 | this.serve(req, res);
|
214 | }
|
215 | else {
|
216 | for (let i = 0; i < evs.length; i++) {
|
217 | evs[i].call(srv, req, res);
|
218 | }
|
219 | }
|
220 | });
|
221 | }
|
222 | |
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 | serve(req, res) {
|
230 | const filename = req.url.replace(this._path, "").replace(/\?.*$/, "");
|
231 | const isMap = dotMapRegex.test(filename);
|
232 | const type = isMap ? "map" : "source";
|
233 |
|
234 |
|
235 | const expectedEtag = '"' + clientVersion + '"';
|
236 | const weakEtag = "W/" + expectedEtag;
|
237 | const etag = req.headers["if-none-match"];
|
238 | if (etag) {
|
239 | if (expectedEtag === etag || weakEtag === etag) {
|
240 | debug("serve client %s 304", type);
|
241 | res.writeHead(304);
|
242 | res.end();
|
243 | return;
|
244 | }
|
245 | }
|
246 | debug("serve client %s", type);
|
247 | res.setHeader("Cache-Control", "public, max-age=0");
|
248 | res.setHeader("Content-Type", "application/" + (isMap ? "json" : "javascript"));
|
249 | res.setHeader("ETag", expectedEtag);
|
250 | Server.sendFile(filename, req, res);
|
251 | }
|
252 | |
253 |
|
254 |
|
255 |
|
256 |
|
257 |
|
258 | static sendFile(filename, req, res) {
|
259 | const readStream = (0, fs_1.createReadStream)(path.join(__dirname, "../client-dist/", filename));
|
260 | const encoding = accepts(req).encodings(["br", "gzip", "deflate"]);
|
261 | const onError = (err) => {
|
262 | if (err) {
|
263 | res.end();
|
264 | }
|
265 | };
|
266 | switch (encoding) {
|
267 | case "br":
|
268 | res.writeHead(200, { "content-encoding": "br" });
|
269 | readStream.pipe((0, zlib_1.createBrotliCompress)()).pipe(res);
|
270 | (0, stream_1.pipeline)(readStream, (0, zlib_1.createBrotliCompress)(), res, onError);
|
271 | break;
|
272 | case "gzip":
|
273 | res.writeHead(200, { "content-encoding": "gzip" });
|
274 | (0, stream_1.pipeline)(readStream, (0, zlib_1.createGzip)(), res, onError);
|
275 | break;
|
276 | case "deflate":
|
277 | res.writeHead(200, { "content-encoding": "deflate" });
|
278 | (0, stream_1.pipeline)(readStream, (0, zlib_1.createDeflate)(), res, onError);
|
279 | break;
|
280 | default:
|
281 | res.writeHead(200);
|
282 | (0, stream_1.pipeline)(readStream, res, onError);
|
283 | }
|
284 | }
|
285 | |
286 |
|
287 |
|
288 |
|
289 |
|
290 |
|
291 |
|
292 | bind(engine) {
|
293 | this.engine = engine;
|
294 | this.engine.on("connection", this.onconnection.bind(this));
|
295 | return this;
|
296 | }
|
297 | |
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 | onconnection(conn) {
|
305 | debug("incoming connection with id %s", conn.id);
|
306 | const client = new client_1.Client(this, conn);
|
307 | if (conn.protocol === 3) {
|
308 |
|
309 | client.connect("/");
|
310 | }
|
311 | return this;
|
312 | }
|
313 | |
314 |
|
315 |
|
316 |
|
317 |
|
318 |
|
319 |
|
320 | of(name, fn) {
|
321 | if (typeof name === "function" || name instanceof RegExp) {
|
322 | const parentNsp = new parent_namespace_1.ParentNamespace(this);
|
323 | debug("initializing parent namespace %s", parentNsp.name);
|
324 | if (typeof name === "function") {
|
325 | this.parentNsps.set(name, parentNsp);
|
326 | }
|
327 | else {
|
328 | this.parentNsps.set((nsp, conn, next) => next(null, name.test(nsp)), parentNsp);
|
329 | }
|
330 | if (fn) {
|
331 |
|
332 | parentNsp.on("connect", fn);
|
333 | }
|
334 | return parentNsp;
|
335 | }
|
336 | if (String(name)[0] !== "/")
|
337 | name = "/" + name;
|
338 | let nsp = this._nsps.get(name);
|
339 | if (!nsp) {
|
340 | debug("initializing namespace %s", name);
|
341 | nsp = new namespace_1.Namespace(this, name);
|
342 | this._nsps.set(name, nsp);
|
343 | if (name !== "/") {
|
344 |
|
345 | this.sockets.emitReserved("new_namespace", nsp);
|
346 | }
|
347 | }
|
348 | if (fn)
|
349 | nsp.on("connect", fn);
|
350 | return nsp;
|
351 | }
|
352 | |
353 |
|
354 |
|
355 |
|
356 |
|
357 |
|
358 | close(fn) {
|
359 | for (const socket of this.sockets.sockets.values()) {
|
360 | socket._onclose("server shutting down");
|
361 | }
|
362 | this.engine.close();
|
363 | if (this.httpServer) {
|
364 | this.httpServer.close(fn);
|
365 | }
|
366 | else {
|
367 | fn && fn();
|
368 | }
|
369 | }
|
370 | |
371 |
|
372 |
|
373 |
|
374 |
|
375 |
|
376 | use(fn) {
|
377 | this.sockets.use(fn);
|
378 | return this;
|
379 | }
|
380 | |
381 |
|
382 |
|
383 |
|
384 |
|
385 |
|
386 |
|
387 | to(room) {
|
388 | return this.sockets.to(room);
|
389 | }
|
390 | |
391 |
|
392 |
|
393 |
|
394 |
|
395 |
|
396 |
|
397 | in(room) {
|
398 | return this.sockets.in(room);
|
399 | }
|
400 | |
401 |
|
402 |
|
403 |
|
404 |
|
405 |
|
406 |
|
407 | except(name) {
|
408 | return this.sockets.except(name);
|
409 | }
|
410 | |
411 |
|
412 |
|
413 |
|
414 |
|
415 |
|
416 | send(...args) {
|
417 | this.sockets.emit("message", ...args);
|
418 | return this;
|
419 | }
|
420 | |
421 |
|
422 |
|
423 |
|
424 |
|
425 |
|
426 | write(...args) {
|
427 | this.sockets.emit("message", ...args);
|
428 | return this;
|
429 | }
|
430 | |
431 |
|
432 |
|
433 |
|
434 |
|
435 |
|
436 |
|
437 | serverSideEmit(ev, ...args) {
|
438 | return this.sockets.serverSideEmit(ev, ...args);
|
439 | }
|
440 | |
441 |
|
442 |
|
443 |
|
444 |
|
445 | allSockets() {
|
446 | return this.sockets.allSockets();
|
447 | }
|
448 | |
449 |
|
450 |
|
451 |
|
452 |
|
453 |
|
454 |
|
455 | compress(compress) {
|
456 | return this.sockets.compress(compress);
|
457 | }
|
458 | |
459 |
|
460 |
|
461 |
|
462 |
|
463 |
|
464 |
|
465 |
|
466 | get volatile() {
|
467 | return this.sockets.volatile;
|
468 | }
|
469 | |
470 |
|
471 |
|
472 |
|
473 |
|
474 |
|
475 | get local() {
|
476 | return this.sockets.local;
|
477 | }
|
478 | |
479 |
|
480 |
|
481 |
|
482 |
|
483 | fetchSockets() {
|
484 | return this.sockets.fetchSockets();
|
485 | }
|
486 | |
487 |
|
488 |
|
489 |
|
490 |
|
491 |
|
492 | socketsJoin(room) {
|
493 | return this.sockets.socketsJoin(room);
|
494 | }
|
495 | |
496 |
|
497 |
|
498 |
|
499 |
|
500 |
|
501 | socketsLeave(room) {
|
502 | return this.sockets.socketsLeave(room);
|
503 | }
|
504 | |
505 |
|
506 |
|
507 |
|
508 |
|
509 |
|
510 | disconnectSockets(close = false) {
|
511 | return this.sockets.disconnectSockets(close);
|
512 | }
|
513 | }
|
514 | exports.Server = Server;
|
515 |
|
516 |
|
517 |
|
518 | const emitterMethods = Object.keys(events_1.EventEmitter.prototype).filter(function (key) {
|
519 | return typeof events_1.EventEmitter.prototype[key] === "function";
|
520 | });
|
521 | emitterMethods.forEach(function (fn) {
|
522 | Server.prototype[fn] = function () {
|
523 | return this.sockets[fn].apply(this.sockets, arguments);
|
524 | };
|
525 | });
|
526 | module.exports = (srv, opts) => new Server(srv, opts);
|
527 | module.exports.Server = Server;
|
528 | module.exports.Namespace = namespace_1.Namespace;
|
529 | module.exports.Socket = socket_1.Socket;
|