isomorfeus-transport 2.0.7 → 2.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/isomorfeus/transport/rack_middleware.rb +1 -0
- data/lib/isomorfeus/transport/version.rb +1 -1
- data/lib/isomorfeus/transport/websocket_client.rb +6 -2
- data/lib/isomorfeus/transport.rb +3 -2
- data/node_modules/.package-lock.json +27 -27
- data/node_modules/ws/LICENSE +19 -19
- data/node_modules/ws/README.md +489 -496
- data/node_modules/ws/browser.js +8 -8
- data/node_modules/ws/index.js +13 -13
- data/node_modules/ws/lib/buffer-util.js +126 -126
- data/node_modules/ws/lib/constants.js +12 -12
- data/node_modules/ws/lib/event-target.js +266 -266
- data/node_modules/ws/lib/extension.js +203 -203
- data/node_modules/ws/lib/limiter.js +55 -55
- data/node_modules/ws/lib/permessage-deflate.js +511 -511
- data/node_modules/ws/lib/receiver.js +618 -612
- data/node_modules/ws/lib/sender.js +478 -414
- data/node_modules/ws/lib/stream.js +159 -180
- data/node_modules/ws/lib/subprotocol.js +62 -62
- data/node_modules/ws/lib/validation.js +124 -124
- data/node_modules/ws/lib/websocket-server.js +485 -485
- data/node_modules/ws/lib/websocket.js +1225 -1144
- data/node_modules/ws/package.json +61 -61
- data/node_modules/ws/wrapper.mjs +8 -8
- data/package.json +1 -1
- metadata +10 -10
@@ -1,203 +1,203 @@
|
|
1
|
-
'use strict';
|
2
|
-
|
3
|
-
const { tokenChars } = require('./validation');
|
4
|
-
|
5
|
-
/**
|
6
|
-
* Adds an offer to the map of extension offers or a parameter to the map of
|
7
|
-
* parameters.
|
8
|
-
*
|
9
|
-
* @param {Object} dest The map of extension offers or parameters
|
10
|
-
* @param {String} name The extension or parameter name
|
11
|
-
* @param {(Object|Boolean|String)} elem The extension parameters or the
|
12
|
-
* parameter value
|
13
|
-
* @private
|
14
|
-
*/
|
15
|
-
function push(dest, name, elem) {
|
16
|
-
if (dest[name] === undefined) dest[name] = [elem];
|
17
|
-
else dest[name].push(elem);
|
18
|
-
}
|
19
|
-
|
20
|
-
/**
|
21
|
-
* Parses the `Sec-WebSocket-Extensions` header into an object.
|
22
|
-
*
|
23
|
-
* @param {String} header The field value of the header
|
24
|
-
* @return {Object} The parsed object
|
25
|
-
* @public
|
26
|
-
*/
|
27
|
-
function parse(header) {
|
28
|
-
const offers = Object.create(null);
|
29
|
-
let params = Object.create(null);
|
30
|
-
let mustUnescape = false;
|
31
|
-
let isEscaping = false;
|
32
|
-
let inQuotes = false;
|
33
|
-
let extensionName;
|
34
|
-
let paramName;
|
35
|
-
let start = -1;
|
36
|
-
let code = -1;
|
37
|
-
let end = -1;
|
38
|
-
let i = 0;
|
39
|
-
|
40
|
-
for (; i < header.length; i++) {
|
41
|
-
code = header.charCodeAt(i);
|
42
|
-
|
43
|
-
if (extensionName === undefined) {
|
44
|
-
if (end === -1 && tokenChars[code] === 1) {
|
45
|
-
if (start === -1) start = i;
|
46
|
-
} else if (
|
47
|
-
i !== 0 &&
|
48
|
-
(code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
|
49
|
-
) {
|
50
|
-
if (end === -1 && start !== -1) end = i;
|
51
|
-
} else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {
|
52
|
-
if (start === -1) {
|
53
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
54
|
-
}
|
55
|
-
|
56
|
-
if (end === -1) end = i;
|
57
|
-
const name = header.slice(start, end);
|
58
|
-
if (code === 0x2c) {
|
59
|
-
push(offers, name, params);
|
60
|
-
params = Object.create(null);
|
61
|
-
} else {
|
62
|
-
extensionName = name;
|
63
|
-
}
|
64
|
-
|
65
|
-
start = end = -1;
|
66
|
-
} else {
|
67
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
68
|
-
}
|
69
|
-
} else if (paramName === undefined) {
|
70
|
-
if (end === -1 && tokenChars[code] === 1) {
|
71
|
-
if (start === -1) start = i;
|
72
|
-
} else if (code === 0x20 || code === 0x09) {
|
73
|
-
if (end === -1 && start !== -1) end = i;
|
74
|
-
} else if (code === 0x3b || code === 0x2c) {
|
75
|
-
if (start === -1) {
|
76
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
77
|
-
}
|
78
|
-
|
79
|
-
if (end === -1) end = i;
|
80
|
-
push(params, header.slice(start, end), true);
|
81
|
-
if (code === 0x2c) {
|
82
|
-
push(offers, extensionName, params);
|
83
|
-
params = Object.create(null);
|
84
|
-
extensionName = undefined;
|
85
|
-
}
|
86
|
-
|
87
|
-
start = end = -1;
|
88
|
-
} else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) {
|
89
|
-
paramName = header.slice(start, i);
|
90
|
-
start = end = -1;
|
91
|
-
} else {
|
92
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
93
|
-
}
|
94
|
-
} else {
|
95
|
-
//
|
96
|
-
// The value of a quoted-string after unescaping must conform to the
|
97
|
-
// token ABNF, so only token characters are valid.
|
98
|
-
// Ref: https://tools.ietf.org/html/rfc6455#section-9.1
|
99
|
-
//
|
100
|
-
if (isEscaping) {
|
101
|
-
if (tokenChars[code] !== 1) {
|
102
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
103
|
-
}
|
104
|
-
if (start === -1) start = i;
|
105
|
-
else if (!mustUnescape) mustUnescape = true;
|
106
|
-
isEscaping = false;
|
107
|
-
} else if (inQuotes) {
|
108
|
-
if (tokenChars[code] === 1) {
|
109
|
-
if (start === -1) start = i;
|
110
|
-
} else if (code === 0x22 /* '"' */ && start !== -1) {
|
111
|
-
inQuotes = false;
|
112
|
-
end = i;
|
113
|
-
} else if (code === 0x5c /* '\' */) {
|
114
|
-
isEscaping = true;
|
115
|
-
} else {
|
116
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
117
|
-
}
|
118
|
-
} else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {
|
119
|
-
inQuotes = true;
|
120
|
-
} else if (end === -1 && tokenChars[code] === 1) {
|
121
|
-
if (start === -1) start = i;
|
122
|
-
} else if (start !== -1 && (code === 0x20 || code === 0x09)) {
|
123
|
-
if (end === -1) end = i;
|
124
|
-
} else if (code === 0x3b || code === 0x2c) {
|
125
|
-
if (start === -1) {
|
126
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
127
|
-
}
|
128
|
-
|
129
|
-
if (end === -1) end = i;
|
130
|
-
let value = header.slice(start, end);
|
131
|
-
if (mustUnescape) {
|
132
|
-
value = value.replace(/\\/g, '');
|
133
|
-
mustUnescape = false;
|
134
|
-
}
|
135
|
-
push(params, paramName, value);
|
136
|
-
if (code === 0x2c) {
|
137
|
-
push(offers, extensionName, params);
|
138
|
-
params = Object.create(null);
|
139
|
-
extensionName = undefined;
|
140
|
-
}
|
141
|
-
|
142
|
-
paramName = undefined;
|
143
|
-
start = end = -1;
|
144
|
-
} else {
|
145
|
-
throw new SyntaxError(`Unexpected character at index ${i}`);
|
146
|
-
}
|
147
|
-
}
|
148
|
-
}
|
149
|
-
|
150
|
-
if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {
|
151
|
-
throw new SyntaxError('Unexpected end of input');
|
152
|
-
}
|
153
|
-
|
154
|
-
if (end === -1) end = i;
|
155
|
-
const token = header.slice(start, end);
|
156
|
-
if (extensionName === undefined) {
|
157
|
-
push(offers, token, params);
|
158
|
-
} else {
|
159
|
-
if (paramName === undefined) {
|
160
|
-
push(params, token, true);
|
161
|
-
} else if (mustUnescape) {
|
162
|
-
push(params, paramName, token.replace(/\\/g, ''));
|
163
|
-
} else {
|
164
|
-
push(params, paramName, token);
|
165
|
-
}
|
166
|
-
push(offers, extensionName, params);
|
167
|
-
}
|
168
|
-
|
169
|
-
return offers;
|
170
|
-
}
|
171
|
-
|
172
|
-
/**
|
173
|
-
* Builds the `Sec-WebSocket-Extensions` header field value.
|
174
|
-
*
|
175
|
-
* @param {Object} extensions The map of extensions and parameters to format
|
176
|
-
* @return {String} A string representing the given object
|
177
|
-
* @public
|
178
|
-
*/
|
179
|
-
function format(extensions) {
|
180
|
-
return Object.keys(extensions)
|
181
|
-
.map((extension) => {
|
182
|
-
let configurations = extensions[extension];
|
183
|
-
if (!Array.isArray(configurations)) configurations = [configurations];
|
184
|
-
return configurations
|
185
|
-
.map((params) => {
|
186
|
-
return [extension]
|
187
|
-
.concat(
|
188
|
-
Object.keys(params).map((k) => {
|
189
|
-
let values = params[k];
|
190
|
-
if (!Array.isArray(values)) values = [values];
|
191
|
-
return values
|
192
|
-
.map((v) => (v === true ? k : `${k}=${v}`))
|
193
|
-
.join('; ');
|
194
|
-
})
|
195
|
-
)
|
196
|
-
.join('; ');
|
197
|
-
})
|
198
|
-
.join(', ');
|
199
|
-
})
|
200
|
-
.join(', ');
|
201
|
-
}
|
202
|
-
|
203
|
-
module.exports = { format, parse };
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const { tokenChars } = require('./validation');
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Adds an offer to the map of extension offers or a parameter to the map of
|
7
|
+
* parameters.
|
8
|
+
*
|
9
|
+
* @param {Object} dest The map of extension offers or parameters
|
10
|
+
* @param {String} name The extension or parameter name
|
11
|
+
* @param {(Object|Boolean|String)} elem The extension parameters or the
|
12
|
+
* parameter value
|
13
|
+
* @private
|
14
|
+
*/
|
15
|
+
function push(dest, name, elem) {
|
16
|
+
if (dest[name] === undefined) dest[name] = [elem];
|
17
|
+
else dest[name].push(elem);
|
18
|
+
}
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Parses the `Sec-WebSocket-Extensions` header into an object.
|
22
|
+
*
|
23
|
+
* @param {String} header The field value of the header
|
24
|
+
* @return {Object} The parsed object
|
25
|
+
* @public
|
26
|
+
*/
|
27
|
+
function parse(header) {
|
28
|
+
const offers = Object.create(null);
|
29
|
+
let params = Object.create(null);
|
30
|
+
let mustUnescape = false;
|
31
|
+
let isEscaping = false;
|
32
|
+
let inQuotes = false;
|
33
|
+
let extensionName;
|
34
|
+
let paramName;
|
35
|
+
let start = -1;
|
36
|
+
let code = -1;
|
37
|
+
let end = -1;
|
38
|
+
let i = 0;
|
39
|
+
|
40
|
+
for (; i < header.length; i++) {
|
41
|
+
code = header.charCodeAt(i);
|
42
|
+
|
43
|
+
if (extensionName === undefined) {
|
44
|
+
if (end === -1 && tokenChars[code] === 1) {
|
45
|
+
if (start === -1) start = i;
|
46
|
+
} else if (
|
47
|
+
i !== 0 &&
|
48
|
+
(code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
|
49
|
+
) {
|
50
|
+
if (end === -1 && start !== -1) end = i;
|
51
|
+
} else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {
|
52
|
+
if (start === -1) {
|
53
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
54
|
+
}
|
55
|
+
|
56
|
+
if (end === -1) end = i;
|
57
|
+
const name = header.slice(start, end);
|
58
|
+
if (code === 0x2c) {
|
59
|
+
push(offers, name, params);
|
60
|
+
params = Object.create(null);
|
61
|
+
} else {
|
62
|
+
extensionName = name;
|
63
|
+
}
|
64
|
+
|
65
|
+
start = end = -1;
|
66
|
+
} else {
|
67
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
68
|
+
}
|
69
|
+
} else if (paramName === undefined) {
|
70
|
+
if (end === -1 && tokenChars[code] === 1) {
|
71
|
+
if (start === -1) start = i;
|
72
|
+
} else if (code === 0x20 || code === 0x09) {
|
73
|
+
if (end === -1 && start !== -1) end = i;
|
74
|
+
} else if (code === 0x3b || code === 0x2c) {
|
75
|
+
if (start === -1) {
|
76
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
77
|
+
}
|
78
|
+
|
79
|
+
if (end === -1) end = i;
|
80
|
+
push(params, header.slice(start, end), true);
|
81
|
+
if (code === 0x2c) {
|
82
|
+
push(offers, extensionName, params);
|
83
|
+
params = Object.create(null);
|
84
|
+
extensionName = undefined;
|
85
|
+
}
|
86
|
+
|
87
|
+
start = end = -1;
|
88
|
+
} else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) {
|
89
|
+
paramName = header.slice(start, i);
|
90
|
+
start = end = -1;
|
91
|
+
} else {
|
92
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
93
|
+
}
|
94
|
+
} else {
|
95
|
+
//
|
96
|
+
// The value of a quoted-string after unescaping must conform to the
|
97
|
+
// token ABNF, so only token characters are valid.
|
98
|
+
// Ref: https://tools.ietf.org/html/rfc6455#section-9.1
|
99
|
+
//
|
100
|
+
if (isEscaping) {
|
101
|
+
if (tokenChars[code] !== 1) {
|
102
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
103
|
+
}
|
104
|
+
if (start === -1) start = i;
|
105
|
+
else if (!mustUnescape) mustUnescape = true;
|
106
|
+
isEscaping = false;
|
107
|
+
} else if (inQuotes) {
|
108
|
+
if (tokenChars[code] === 1) {
|
109
|
+
if (start === -1) start = i;
|
110
|
+
} else if (code === 0x22 /* '"' */ && start !== -1) {
|
111
|
+
inQuotes = false;
|
112
|
+
end = i;
|
113
|
+
} else if (code === 0x5c /* '\' */) {
|
114
|
+
isEscaping = true;
|
115
|
+
} else {
|
116
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
117
|
+
}
|
118
|
+
} else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {
|
119
|
+
inQuotes = true;
|
120
|
+
} else if (end === -1 && tokenChars[code] === 1) {
|
121
|
+
if (start === -1) start = i;
|
122
|
+
} else if (start !== -1 && (code === 0x20 || code === 0x09)) {
|
123
|
+
if (end === -1) end = i;
|
124
|
+
} else if (code === 0x3b || code === 0x2c) {
|
125
|
+
if (start === -1) {
|
126
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
127
|
+
}
|
128
|
+
|
129
|
+
if (end === -1) end = i;
|
130
|
+
let value = header.slice(start, end);
|
131
|
+
if (mustUnescape) {
|
132
|
+
value = value.replace(/\\/g, '');
|
133
|
+
mustUnescape = false;
|
134
|
+
}
|
135
|
+
push(params, paramName, value);
|
136
|
+
if (code === 0x2c) {
|
137
|
+
push(offers, extensionName, params);
|
138
|
+
params = Object.create(null);
|
139
|
+
extensionName = undefined;
|
140
|
+
}
|
141
|
+
|
142
|
+
paramName = undefined;
|
143
|
+
start = end = -1;
|
144
|
+
} else {
|
145
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {
|
151
|
+
throw new SyntaxError('Unexpected end of input');
|
152
|
+
}
|
153
|
+
|
154
|
+
if (end === -1) end = i;
|
155
|
+
const token = header.slice(start, end);
|
156
|
+
if (extensionName === undefined) {
|
157
|
+
push(offers, token, params);
|
158
|
+
} else {
|
159
|
+
if (paramName === undefined) {
|
160
|
+
push(params, token, true);
|
161
|
+
} else if (mustUnescape) {
|
162
|
+
push(params, paramName, token.replace(/\\/g, ''));
|
163
|
+
} else {
|
164
|
+
push(params, paramName, token);
|
165
|
+
}
|
166
|
+
push(offers, extensionName, params);
|
167
|
+
}
|
168
|
+
|
169
|
+
return offers;
|
170
|
+
}
|
171
|
+
|
172
|
+
/**
|
173
|
+
* Builds the `Sec-WebSocket-Extensions` header field value.
|
174
|
+
*
|
175
|
+
* @param {Object} extensions The map of extensions and parameters to format
|
176
|
+
* @return {String} A string representing the given object
|
177
|
+
* @public
|
178
|
+
*/
|
179
|
+
function format(extensions) {
|
180
|
+
return Object.keys(extensions)
|
181
|
+
.map((extension) => {
|
182
|
+
let configurations = extensions[extension];
|
183
|
+
if (!Array.isArray(configurations)) configurations = [configurations];
|
184
|
+
return configurations
|
185
|
+
.map((params) => {
|
186
|
+
return [extension]
|
187
|
+
.concat(
|
188
|
+
Object.keys(params).map((k) => {
|
189
|
+
let values = params[k];
|
190
|
+
if (!Array.isArray(values)) values = [values];
|
191
|
+
return values
|
192
|
+
.map((v) => (v === true ? k : `${k}=${v}`))
|
193
|
+
.join('; ');
|
194
|
+
})
|
195
|
+
)
|
196
|
+
.join('; ');
|
197
|
+
})
|
198
|
+
.join(', ');
|
199
|
+
})
|
200
|
+
.join(', ');
|
201
|
+
}
|
202
|
+
|
203
|
+
module.exports = { format, parse };
|
@@ -1,55 +1,55 @@
|
|
1
|
-
'use strict';
|
2
|
-
|
3
|
-
const kDone = Symbol('kDone');
|
4
|
-
const kRun = Symbol('kRun');
|
5
|
-
|
6
|
-
/**
|
7
|
-
* A very simple job queue with adjustable concurrency. Adapted from
|
8
|
-
* https://github.com/STRML/async-limiter
|
9
|
-
*/
|
10
|
-
class Limiter {
|
11
|
-
/**
|
12
|
-
* Creates a new `Limiter`.
|
13
|
-
*
|
14
|
-
* @param {Number} [concurrency=Infinity] The maximum number of jobs allowed
|
15
|
-
* to run concurrently
|
16
|
-
*/
|
17
|
-
constructor(concurrency) {
|
18
|
-
this[kDone] = () => {
|
19
|
-
this.pending--;
|
20
|
-
this[kRun]();
|
21
|
-
};
|
22
|
-
this.concurrency = concurrency || Infinity;
|
23
|
-
this.jobs = [];
|
24
|
-
this.pending = 0;
|
25
|
-
}
|
26
|
-
|
27
|
-
/**
|
28
|
-
* Adds a job to the queue.
|
29
|
-
*
|
30
|
-
* @param {Function} job The job to run
|
31
|
-
* @public
|
32
|
-
*/
|
33
|
-
add(job) {
|
34
|
-
this.jobs.push(job);
|
35
|
-
this[kRun]();
|
36
|
-
}
|
37
|
-
|
38
|
-
/**
|
39
|
-
* Removes a job from the queue and runs it if possible.
|
40
|
-
*
|
41
|
-
* @private
|
42
|
-
*/
|
43
|
-
[kRun]() {
|
44
|
-
if (this.pending === this.concurrency) return;
|
45
|
-
|
46
|
-
if (this.jobs.length) {
|
47
|
-
const job = this.jobs.shift();
|
48
|
-
|
49
|
-
this.pending++;
|
50
|
-
job(this[kDone]);
|
51
|
-
}
|
52
|
-
}
|
53
|
-
}
|
54
|
-
|
55
|
-
module.exports = Limiter;
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const kDone = Symbol('kDone');
|
4
|
+
const kRun = Symbol('kRun');
|
5
|
+
|
6
|
+
/**
|
7
|
+
* A very simple job queue with adjustable concurrency. Adapted from
|
8
|
+
* https://github.com/STRML/async-limiter
|
9
|
+
*/
|
10
|
+
class Limiter {
|
11
|
+
/**
|
12
|
+
* Creates a new `Limiter`.
|
13
|
+
*
|
14
|
+
* @param {Number} [concurrency=Infinity] The maximum number of jobs allowed
|
15
|
+
* to run concurrently
|
16
|
+
*/
|
17
|
+
constructor(concurrency) {
|
18
|
+
this[kDone] = () => {
|
19
|
+
this.pending--;
|
20
|
+
this[kRun]();
|
21
|
+
};
|
22
|
+
this.concurrency = concurrency || Infinity;
|
23
|
+
this.jobs = [];
|
24
|
+
this.pending = 0;
|
25
|
+
}
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Adds a job to the queue.
|
29
|
+
*
|
30
|
+
* @param {Function} job The job to run
|
31
|
+
* @public
|
32
|
+
*/
|
33
|
+
add(job) {
|
34
|
+
this.jobs.push(job);
|
35
|
+
this[kRun]();
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Removes a job from the queue and runs it if possible.
|
40
|
+
*
|
41
|
+
* @private
|
42
|
+
*/
|
43
|
+
[kRun]() {
|
44
|
+
if (this.pending === this.concurrency) return;
|
45
|
+
|
46
|
+
if (this.jobs.length) {
|
47
|
+
const job = this.jobs.shift();
|
48
|
+
|
49
|
+
this.pending++;
|
50
|
+
job(this[kDone]);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
module.exports = Limiter;
|