isomorfeus-transport 2.5.5 → 22.9.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/isomorfeus/core_ext/hash/deep_merge.rb +34 -0
  3. data/lib/isomorfeus/core_ext/kernel.rb +56 -0
  4. data/lib/isomorfeus/core_ext/object/deep_dup.rb +53 -0
  5. data/lib/isomorfeus/core_ext/object/duplicable.rb +60 -0
  6. data/lib/isomorfeus/transport/compressor_rack.rb +1 -1
  7. data/lib/isomorfeus/transport/config.rb +37 -0
  8. data/lib/isomorfeus/transport/rack_middleware.rb +16 -9
  9. data/lib/isomorfeus/transport/request_agent.rb +1 -0
  10. data/lib/isomorfeus/transport/server_socket_processor.rb +13 -1
  11. data/lib/isomorfeus/transport/version.rb +1 -1
  12. data/lib/isomorfeus/transport.rb +45 -38
  13. data/lib/isomorfeus-transport.rb +25 -16
  14. data/lib/lucid_channel.rb +103 -0
  15. data/lib/lucid_handler.rb +25 -0
  16. metadata +40 -90
  17. data/lib/isomorfeus/transport/handler/authentication_handler.rb +0 -55
  18. data/lib/isomorfeus/transport/imports.rb +0 -10
  19. data/lib/isomorfeus/transport/ssr_login.rb +0 -30
  20. data/lib/lucid_channel/base.rb +0 -8
  21. data/lib/lucid_channel/mixin.rb +0 -105
  22. data/lib/lucid_handler/base.rb +0 -8
  23. data/lib/lucid_handler/mixin.rb +0 -27
  24. data/node_modules/.package-lock.json +0 -27
  25. data/node_modules/ws/LICENSE +0 -19
  26. data/node_modules/ws/README.md +0 -489
  27. data/node_modules/ws/browser.js +0 -8
  28. data/node_modules/ws/index.js +0 -13
  29. data/node_modules/ws/lib/buffer-util.js +0 -126
  30. data/node_modules/ws/lib/constants.js +0 -12
  31. data/node_modules/ws/lib/event-target.js +0 -266
  32. data/node_modules/ws/lib/extension.js +0 -203
  33. data/node_modules/ws/lib/limiter.js +0 -55
  34. data/node_modules/ws/lib/permessage-deflate.js +0 -511
  35. data/node_modules/ws/lib/receiver.js +0 -618
  36. data/node_modules/ws/lib/sender.js +0 -478
  37. data/node_modules/ws/lib/stream.js +0 -159
  38. data/node_modules/ws/lib/subprotocol.js +0 -62
  39. data/node_modules/ws/lib/validation.js +0 -124
  40. data/node_modules/ws/lib/websocket-server.js +0 -488
  41. data/node_modules/ws/lib/websocket.js +0 -1264
  42. data/node_modules/ws/package.json +0 -61
  43. data/node_modules/ws/wrapper.mjs +0 -8
  44. data/package.json +0 -6
@@ -1,124 +0,0 @@
1
- 'use strict';
2
-
3
- //
4
- // Allowed token characters:
5
- //
6
- // '!', '#', '$', '%', '&', ''', '*', '+', '-',
7
- // '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'
8
- //
9
- // tokenChars[32] === 0 // ' '
10
- // tokenChars[33] === 1 // '!'
11
- // tokenChars[34] === 0 // '"'
12
- // ...
13
- //
14
- // prettier-ignore
15
- const tokenChars = [
16
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
17
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
18
- 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
19
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
20
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
21
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
22
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
23
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127
24
- ];
25
-
26
- /**
27
- * Checks if a status code is allowed in a close frame.
28
- *
29
- * @param {Number} code The status code
30
- * @return {Boolean} `true` if the status code is valid, else `false`
31
- * @public
32
- */
33
- function isValidStatusCode(code) {
34
- return (
35
- (code >= 1000 &&
36
- code <= 1014 &&
37
- code !== 1004 &&
38
- code !== 1005 &&
39
- code !== 1006) ||
40
- (code >= 3000 && code <= 4999)
41
- );
42
- }
43
-
44
- /**
45
- * Checks if a given buffer contains only correct UTF-8.
46
- * Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by
47
- * Markus Kuhn.
48
- *
49
- * @param {Buffer} buf The buffer to check
50
- * @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false`
51
- * @public
52
- */
53
- function _isValidUTF8(buf) {
54
- const len = buf.length;
55
- let i = 0;
56
-
57
- while (i < len) {
58
- if ((buf[i] & 0x80) === 0) {
59
- // 0xxxxxxx
60
- i++;
61
- } else if ((buf[i] & 0xe0) === 0xc0) {
62
- // 110xxxxx 10xxxxxx
63
- if (
64
- i + 1 === len ||
65
- (buf[i + 1] & 0xc0) !== 0x80 ||
66
- (buf[i] & 0xfe) === 0xc0 // Overlong
67
- ) {
68
- return false;
69
- }
70
-
71
- i += 2;
72
- } else if ((buf[i] & 0xf0) === 0xe0) {
73
- // 1110xxxx 10xxxxxx 10xxxxxx
74
- if (
75
- i + 2 >= len ||
76
- (buf[i + 1] & 0xc0) !== 0x80 ||
77
- (buf[i + 2] & 0xc0) !== 0x80 ||
78
- (buf[i] === 0xe0 && (buf[i + 1] & 0xe0) === 0x80) || // Overlong
79
- (buf[i] === 0xed && (buf[i + 1] & 0xe0) === 0xa0) // Surrogate (U+D800 - U+DFFF)
80
- ) {
81
- return false;
82
- }
83
-
84
- i += 3;
85
- } else if ((buf[i] & 0xf8) === 0xf0) {
86
- // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
87
- if (
88
- i + 3 >= len ||
89
- (buf[i + 1] & 0xc0) !== 0x80 ||
90
- (buf[i + 2] & 0xc0) !== 0x80 ||
91
- (buf[i + 3] & 0xc0) !== 0x80 ||
92
- (buf[i] === 0xf0 && (buf[i + 1] & 0xf0) === 0x80) || // Overlong
93
- (buf[i] === 0xf4 && buf[i + 1] > 0x8f) ||
94
- buf[i] > 0xf4 // > U+10FFFF
95
- ) {
96
- return false;
97
- }
98
-
99
- i += 4;
100
- } else {
101
- return false;
102
- }
103
- }
104
-
105
- return true;
106
- }
107
-
108
- try {
109
- const isValidUTF8 = require('utf-8-validate');
110
-
111
- module.exports = {
112
- isValidStatusCode,
113
- isValidUTF8(buf) {
114
- return buf.length < 150 ? _isValidUTF8(buf) : isValidUTF8(buf);
115
- },
116
- tokenChars
117
- };
118
- } catch (e) /* istanbul ignore next */ {
119
- module.exports = {
120
- isValidStatusCode,
121
- isValidUTF8: _isValidUTF8,
122
- tokenChars
123
- };
124
- }
@@ -1,488 +0,0 @@
1
- /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^net|tls|https$" }] */
2
-
3
- 'use strict';
4
-
5
- const EventEmitter = require('events');
6
- const http = require('http');
7
- const https = require('https');
8
- const net = require('net');
9
- const tls = require('tls');
10
- const { createHash } = require('crypto');
11
-
12
- const extension = require('./extension');
13
- const PerMessageDeflate = require('./permessage-deflate');
14
- const subprotocol = require('./subprotocol');
15
- const WebSocket = require('./websocket');
16
- const { GUID, kWebSocket } = require('./constants');
17
-
18
- const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
19
-
20
- const RUNNING = 0;
21
- const CLOSING = 1;
22
- const CLOSED = 2;
23
-
24
- /**
25
- * Class representing a WebSocket server.
26
- *
27
- * @extends EventEmitter
28
- */
29
- class WebSocketServer extends EventEmitter {
30
- /**
31
- * Create a `WebSocketServer` instance.
32
- *
33
- * @param {Object} options Configuration options
34
- * @param {Number} [options.backlog=511] The maximum length of the queue of
35
- * pending connections
36
- * @param {Boolean} [options.clientTracking=true] Specifies whether or not to
37
- * track clients
38
- * @param {Function} [options.handleProtocols] A hook to handle protocols
39
- * @param {String} [options.host] The hostname where to bind the server
40
- * @param {Number} [options.maxPayload=104857600] The maximum allowed message
41
- * size
42
- * @param {Boolean} [options.noServer=false] Enable no server mode
43
- * @param {String} [options.path] Accept only connections matching this path
44
- * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable
45
- * permessage-deflate
46
- * @param {Number} [options.port] The port where to bind the server
47
- * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S
48
- * server to use
49
- * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
50
- * not to skip UTF-8 validation for text and close messages
51
- * @param {Function} [options.verifyClient] A hook to reject connections
52
- * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket`
53
- * class to use. It must be the `WebSocket` class or class that extends it
54
- * @param {Function} [callback] A listener for the `listening` event
55
- */
56
- constructor(options, callback) {
57
- super();
58
-
59
- options = {
60
- maxPayload: 100 * 1024 * 1024,
61
- skipUTF8Validation: false,
62
- perMessageDeflate: false,
63
- handleProtocols: null,
64
- clientTracking: true,
65
- verifyClient: null,
66
- noServer: false,
67
- backlog: null, // use default (511 as implemented in net.js)
68
- server: null,
69
- host: null,
70
- path: null,
71
- port: null,
72
- WebSocket,
73
- ...options
74
- };
75
-
76
- if (
77
- (options.port == null && !options.server && !options.noServer) ||
78
- (options.port != null && (options.server || options.noServer)) ||
79
- (options.server && options.noServer)
80
- ) {
81
- throw new TypeError(
82
- 'One and only one of the "port", "server", or "noServer" options ' +
83
- 'must be specified'
84
- );
85
- }
86
-
87
- if (options.port != null) {
88
- this._server = http.createServer((req, res) => {
89
- const body = http.STATUS_CODES[426];
90
-
91
- res.writeHead(426, {
92
- 'Content-Length': body.length,
93
- 'Content-Type': 'text/plain'
94
- });
95
- res.end(body);
96
- });
97
- this._server.listen(
98
- options.port,
99
- options.host,
100
- options.backlog,
101
- callback
102
- );
103
- } else if (options.server) {
104
- this._server = options.server;
105
- }
106
-
107
- if (this._server) {
108
- const emitConnection = this.emit.bind(this, 'connection');
109
-
110
- this._removeListeners = addListeners(this._server, {
111
- listening: this.emit.bind(this, 'listening'),
112
- error: this.emit.bind(this, 'error'),
113
- upgrade: (req, socket, head) => {
114
- this.handleUpgrade(req, socket, head, emitConnection);
115
- }
116
- });
117
- }
118
-
119
- if (options.perMessageDeflate === true) options.perMessageDeflate = {};
120
- if (options.clientTracking) {
121
- this.clients = new Set();
122
- this._shouldEmitClose = false;
123
- }
124
-
125
- this.options = options;
126
- this._state = RUNNING;
127
- }
128
-
129
- /**
130
- * Returns the bound address, the address family name, and port of the server
131
- * as reported by the operating system if listening on an IP socket.
132
- * If the server is listening on a pipe or UNIX domain socket, the name is
133
- * returned as a string.
134
- *
135
- * @return {(Object|String|null)} The address of the server
136
- * @public
137
- */
138
- address() {
139
- if (this.options.noServer) {
140
- throw new Error('The server is operating in "noServer" mode');
141
- }
142
-
143
- if (!this._server) return null;
144
- return this._server.address();
145
- }
146
-
147
- /**
148
- * Stop the server from accepting new connections and emit the `'close'` event
149
- * when all existing connections are closed.
150
- *
151
- * @param {Function} [cb] A one-time listener for the `'close'` event
152
- * @public
153
- */
154
- close(cb) {
155
- if (this._state === CLOSED) {
156
- if (cb) {
157
- this.once('close', () => {
158
- cb(new Error('The server is not running'));
159
- });
160
- }
161
-
162
- process.nextTick(emitClose, this);
163
- return;
164
- }
165
-
166
- if (cb) this.once('close', cb);
167
-
168
- if (this._state === CLOSING) return;
169
- this._state = CLOSING;
170
-
171
- if (this.options.noServer || this.options.server) {
172
- if (this._server) {
173
- this._removeListeners();
174
- this._removeListeners = this._server = null;
175
- }
176
-
177
- if (this.clients) {
178
- if (!this.clients.size) {
179
- process.nextTick(emitClose, this);
180
- } else {
181
- this._shouldEmitClose = true;
182
- }
183
- } else {
184
- process.nextTick(emitClose, this);
185
- }
186
- } else {
187
- const server = this._server;
188
-
189
- this._removeListeners();
190
- this._removeListeners = this._server = null;
191
-
192
- //
193
- // The HTTP/S server was created internally. Close it, and rely on its
194
- // `'close'` event.
195
- //
196
- server.close(() => {
197
- emitClose(this);
198
- });
199
- }
200
- }
201
-
202
- /**
203
- * See if a given request should be handled by this server instance.
204
- *
205
- * @param {http.IncomingMessage} req Request object to inspect
206
- * @return {Boolean} `true` if the request is valid, else `false`
207
- * @public
208
- */
209
- shouldHandle(req) {
210
- if (this.options.path) {
211
- const index = req.url.indexOf('?');
212
- const pathname = index !== -1 ? req.url.slice(0, index) : req.url;
213
-
214
- if (pathname !== this.options.path) return false;
215
- }
216
-
217
- return true;
218
- }
219
-
220
- /**
221
- * Handle a HTTP Upgrade request.
222
- *
223
- * @param {http.IncomingMessage} req The request object
224
- * @param {(net.Socket|tls.Socket)} socket The network socket between the
225
- * server and client
226
- * @param {Buffer} head The first packet of the upgraded stream
227
- * @param {Function} cb Callback
228
- * @public
229
- */
230
- handleUpgrade(req, socket, head, cb) {
231
- socket.on('error', socketOnError);
232
-
233
- const key =
234
- req.headers['sec-websocket-key'] !== undefined
235
- ? req.headers['sec-websocket-key']
236
- : false;
237
- const version = +req.headers['sec-websocket-version'];
238
-
239
- if (
240
- req.method !== 'GET' ||
241
- req.headers.upgrade.toLowerCase() !== 'websocket' ||
242
- !key ||
243
- !keyRegex.test(key) ||
244
- (version !== 8 && version !== 13) ||
245
- !this.shouldHandle(req)
246
- ) {
247
- return abortHandshake(socket, 400);
248
- }
249
-
250
- const secWebSocketProtocol = req.headers['sec-websocket-protocol'];
251
- let protocols = new Set();
252
-
253
- if (secWebSocketProtocol !== undefined) {
254
- try {
255
- protocols = subprotocol.parse(secWebSocketProtocol);
256
- } catch (err) {
257
- return abortHandshake(socket, 400);
258
- }
259
- }
260
-
261
- const secWebSocketExtensions = req.headers['sec-websocket-extensions'];
262
- const extensions = {};
263
-
264
- if (
265
- this.options.perMessageDeflate &&
266
- secWebSocketExtensions !== undefined
267
- ) {
268
- const perMessageDeflate = new PerMessageDeflate(
269
- this.options.perMessageDeflate,
270
- true,
271
- this.options.maxPayload
272
- );
273
-
274
- try {
275
- const offers = extension.parse(secWebSocketExtensions);
276
-
277
- if (offers[PerMessageDeflate.extensionName]) {
278
- perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);
279
- extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
280
- }
281
- } catch (err) {
282
- return abortHandshake(socket, 400);
283
- }
284
- }
285
-
286
- //
287
- // Optionally call external client verification handler.
288
- //
289
- if (this.options.verifyClient) {
290
- const info = {
291
- origin:
292
- req.headers[`${version === 8 ? 'sec-websocket-origin' : 'origin'}`],
293
- secure: !!(req.socket.authorized || req.socket.encrypted),
294
- req
295
- };
296
-
297
- if (this.options.verifyClient.length === 2) {
298
- this.options.verifyClient(info, (verified, code, message, headers) => {
299
- if (!verified) {
300
- return abortHandshake(socket, code || 401, message, headers);
301
- }
302
-
303
- this.completeUpgrade(
304
- extensions,
305
- key,
306
- protocols,
307
- req,
308
- socket,
309
- head,
310
- cb
311
- );
312
- });
313
- return;
314
- }
315
-
316
- if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
317
- }
318
-
319
- this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);
320
- }
321
-
322
- /**
323
- * Upgrade the connection to WebSocket.
324
- *
325
- * @param {Object} extensions The accepted extensions
326
- * @param {String} key The value of the `Sec-WebSocket-Key` header
327
- * @param {Set} protocols The subprotocols
328
- * @param {http.IncomingMessage} req The request object
329
- * @param {(net.Socket|tls.Socket)} socket The network socket between the
330
- * server and client
331
- * @param {Buffer} head The first packet of the upgraded stream
332
- * @param {Function} cb Callback
333
- * @throws {Error} If called more than once with the same socket
334
- * @private
335
- */
336
- completeUpgrade(extensions, key, protocols, req, socket, head, cb) {
337
- //
338
- // Destroy the socket if the client has already sent a FIN packet.
339
- //
340
- if (!socket.readable || !socket.writable) return socket.destroy();
341
-
342
- if (socket[kWebSocket]) {
343
- throw new Error(
344
- 'server.handleUpgrade() was called more than once with the same ' +
345
- 'socket, possibly due to a misconfiguration'
346
- );
347
- }
348
-
349
- if (this._state > RUNNING) return abortHandshake(socket, 503);
350
-
351
- const digest = createHash('sha1')
352
- .update(key + GUID)
353
- .digest('base64');
354
-
355
- const headers = [
356
- 'HTTP/1.1 101 Switching Protocols',
357
- 'Upgrade: websocket',
358
- 'Connection: Upgrade',
359
- `Sec-WebSocket-Accept: ${digest}`
360
- ];
361
-
362
- const ws = new this.options.WebSocket(null);
363
-
364
- if (protocols.size) {
365
- //
366
- // Optionally call external protocol selection handler.
367
- //
368
- const protocol = this.options.handleProtocols
369
- ? this.options.handleProtocols(protocols, req)
370
- : protocols.values().next().value;
371
-
372
- if (protocol) {
373
- headers.push(`Sec-WebSocket-Protocol: ${protocol}`);
374
- ws._protocol = protocol;
375
- }
376
- }
377
-
378
- if (extensions[PerMessageDeflate.extensionName]) {
379
- const params = extensions[PerMessageDeflate.extensionName].params;
380
- const value = extension.format({
381
- [PerMessageDeflate.extensionName]: [params]
382
- });
383
- headers.push(`Sec-WebSocket-Extensions: ${value}`);
384
- ws._extensions = extensions;
385
- }
386
-
387
- //
388
- // Allow external modification/inspection of handshake headers.
389
- //
390
- this.emit('headers', headers, req);
391
-
392
- socket.write(headers.concat('\r\n').join('\r\n'));
393
- socket.removeListener('error', socketOnError);
394
-
395
- ws.setSocket(socket, head, {
396
- maxPayload: this.options.maxPayload,
397
- skipUTF8Validation: this.options.skipUTF8Validation
398
- });
399
-
400
- if (this.clients) {
401
- this.clients.add(ws);
402
- ws.on('close', () => {
403
- this.clients.delete(ws);
404
-
405
- if (this._shouldEmitClose && !this.clients.size) {
406
- process.nextTick(emitClose, this);
407
- }
408
- });
409
- }
410
-
411
- cb(ws, req);
412
- }
413
- }
414
-
415
- module.exports = WebSocketServer;
416
-
417
- /**
418
- * Add event listeners on an `EventEmitter` using a map of <event, listener>
419
- * pairs.
420
- *
421
- * @param {EventEmitter} server The event emitter
422
- * @param {Object.<String, Function>} map The listeners to add
423
- * @return {Function} A function that will remove the added listeners when
424
- * called
425
- * @private
426
- */
427
- function addListeners(server, map) {
428
- for (const event of Object.keys(map)) server.on(event, map[event]);
429
-
430
- return function removeListeners() {
431
- for (const event of Object.keys(map)) {
432
- server.removeListener(event, map[event]);
433
- }
434
- };
435
- }
436
-
437
- /**
438
- * Emit a `'close'` event on an `EventEmitter`.
439
- *
440
- * @param {EventEmitter} server The event emitter
441
- * @private
442
- */
443
- function emitClose(server) {
444
- server._state = CLOSED;
445
- server.emit('close');
446
- }
447
-
448
- /**
449
- * Handle premature socket errors.
450
- *
451
- * @private
452
- */
453
- function socketOnError() {
454
- this.destroy();
455
- }
456
-
457
- /**
458
- * Close the connection when preconditions are not fulfilled.
459
- *
460
- * @param {(net.Socket|tls.Socket)} socket The socket of the upgrade request
461
- * @param {Number} code The HTTP response status code
462
- * @param {String} [message] The HTTP response body
463
- * @param {Object} [headers] Additional HTTP response headers
464
- * @private
465
- */
466
- function abortHandshake(socket, code, message, headers) {
467
- if (socket.writable) {
468
- message = message || http.STATUS_CODES[code];
469
- headers = {
470
- Connection: 'close',
471
- 'Content-Type': 'text/html',
472
- 'Content-Length': Buffer.byteLength(message),
473
- ...headers
474
- };
475
-
476
- socket.write(
477
- `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` +
478
- Object.keys(headers)
479
- .map((h) => `${h}: ${headers[h]}`)
480
- .join('\r\n') +
481
- '\r\n\r\n' +
482
- message
483
- );
484
- }
485
-
486
- socket.removeListener('error', socketOnError);
487
- socket.destroy();
488
- }