1
0
mirror of https://github.com/S2-/minifyfromhtml.git synced 2025-08-02 12:00:03 +02:00

update modules

This commit is contained in:
s2
2020-07-20 16:16:07 +02:00
parent 783511ce12
commit 2b23424b86
785 changed files with 91905 additions and 56057 deletions

139
node_modules/ws/README.md generated vendored
View File

@@ -1,8 +1,8 @@
# ws: a Node.js WebSocket library
[![Version npm](https://img.shields.io/npm/v/ws.svg?logo=npm)](https://www.npmjs.com/package/ws)
[![Linux Build](https://img.shields.io/travis/websockets/ws/master.svg?logo=travis)](https://travis-ci.org/websockets/ws)
[![Windows Build](https://img.shields.io/appveyor/ci/lpinca/ws/master.svg?logo=appveyor)](https://ci.appveyor.com/project/lpinca/ws)
[![Build](https://img.shields.io/travis/websockets/ws/master.svg?logo=travis)](https://travis-ci.com/websockets/ws)
[![Windows x86 Build](https://img.shields.io/appveyor/ci/lpinca/ws/master.svg?logo=appveyor)](https://ci.appveyor.com/project/lpinca/ws)
[![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg)](https://coveralls.io/github/websockets/ws)
ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and
@@ -32,10 +32,11 @@ can use one of the many wrappers available on npm, like
- [Simple server](#simple-server)
- [External HTTP/S server](#external-https-server)
- [Multiple servers sharing a single HTTP/S server](#multiple-servers-sharing-a-single-https-server)
- [Client authentication](#client-authentication)
- [Server broadcast](#server-broadcast)
- [echo.websocket.org demo](#echowebsocketorg-demo)
- [Use the Node.js streams API](#use-the-nodejs-streams-api)
- [Other examples](#other-examples)
- [Error handling best practices](#error-handling-best-practices)
- [FAQ](#faq)
- [How to get the IP address of the client?](#how-to-get-the-ip-address-of-the-client)
- [How to detect and close broken connections?](#how-to-detect-and-close-broken-connections)
@@ -70,7 +71,8 @@ necessarily need to have a C++ compiler installed on your machine.
## API docs
See [`/doc/ws.md`](./doc/ws.md) for Node.js-like docs for the ws classes.
See [`/doc/ws.md`](./doc/ws.md) for Node.js-like documentation of ws classes and
utility functions.
## WebSocket compression
@@ -193,7 +195,7 @@ const fs = require('fs');
const https = require('https');
const WebSocket = require('ws');
const server = new https.createServer({
const server = https.createServer({
cert: fs.readFileSync('/path/to/cert.pem'),
key: fs.readFileSync('/path/to/key.pem')
});
@@ -215,6 +217,7 @@ server.listen(8080);
```js
const http = require('http');
const WebSocket = require('ws');
const url = require('url');
const server = http.createServer();
const wss1 = new WebSocket.Server({ noServer: true });
@@ -247,25 +250,72 @@ server.on('upgrade', function upgrade(request, socket, head) {
server.listen(8080);
```
### Client authentication
```js
const http = require('http');
const WebSocket = require('ws');
const server = http.createServer();
const wss = new WebSocket.Server({ noServer: true });
wss.on('connection', function connection(ws, request, client) {
ws.on('message', function message(msg) {
console.log(`Received message ${msg} from user ${client}`);
});
});
server.on('upgrade', function upgrade(request, socket, head) {
// This function is not defined on purpose. Implement it with your own logic.
authenticate(request, (err, client) => {
if (err || !client) {
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
}
wss.handleUpgrade(request, socket, head, function done(ws) {
wss.emit('connection', ws, request, client);
});
});
});
server.listen(8080);
```
Also see the provided [example][session-parse-example] using `express-session`.
### Server broadcast
A client WebSocket broadcasting to all connected WebSocket clients, including
itself.
```js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
// Broadcast to all.
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(data) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
});
};
});
```
A client WebSocket broadcasting to every other connected WebSocket clients,
excluding itself.
```js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(data) {
// Broadcast to everyone else.
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(data);
@@ -302,6 +352,21 @@ ws.on('message', function incoming(data) {
});
```
### Use the Node.js streams API
```js
const WebSocket = require('ws');
const ws = new WebSocket('wss://echo.websocket.org/', {
origin: 'https://websocket.org'
});
const duplex = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' });
duplex.pipe(process.stdout);
process.stdin.pipe(duplex);
```
### Other examples
For a full example with a browser client communicating with a ws server, see the
@@ -309,30 +374,6 @@ examples folder.
Otherwise, see the test cases.
## Error handling best practices
```js
// If the WebSocket is closed before the following send is attempted
ws.send('something');
// Errors (both immediate and async write errors) can be detected in an optional
// callback. The callback is also the only way of being notified that data has
// actually been sent.
ws.send('something', function ack(error) {
// If error is not defined, the send has been completed, otherwise the error
// object will indicate what failed.
});
// Immediate errors can also be handled with `try...catch`, but **note** that
// since sends are inherently asynchronous, socket write failures will *not* be
// captured when this technique is used.
try {
ws.send('something');
} catch (e) {
/* handle error */
}
```
## FAQ
### How to get the IP address of the client?
@@ -345,7 +386,7 @@ const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws, req) {
const ip = req.connection.remoteAddress;
const ip = req.socket.remoteAddress;
});
```
@@ -391,6 +432,10 @@ const interval = setInterval(function ping() {
ws.ping(noop);
});
}, 30000);
wss.on('close', function close() {
clearInterval(interval);
});
```
Pong messages are automatically sent in response to ping messages as required by
@@ -406,9 +451,10 @@ const WebSocket = require('ws');
function heartbeat() {
clearTimeout(this.pingTimeout);
// Use `WebSocket#terminate()` and not `WebSocket#close()`. Delay should be
// equal to the interval at which your server sends out pings plus a
// conservative assumption of the latency.
// Use `WebSocket#terminate()`, which immediately destroys the connection,
// instead of `WebSocket#close()`, which waits for the close timer.
// Delay should be equal to the interval at which your server
// sends out pings plus a conservative assumption of the latency.
this.pingTimeout = setTimeout(() => {
this.terminate();
}, 30000 + 1000);
@@ -436,14 +482,15 @@ We're using the GitHub [releases][changelog] for changelog entries.
[MIT](LICENSE)
[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent
[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent
[client-report]: http://websockets.github.io/ws/autobahn/clients/
[server-report]: http://websockets.github.io/ws/autobahn/servers/
[permessage-deflate]: https://tools.ietf.org/html/rfc7692
[changelog]: https://github.com/websockets/ws/releases
[client-report]: http://websockets.github.io/ws/autobahn/clients/
[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent
[node-zlib-bug]: https://github.com/nodejs/node/issues/8871
[node-zlib-deflaterawdocs]:
https://nodejs.org/api/zlib.html#zlib_zlib_createdeflateraw_options
[permessage-deflate]: https://tools.ietf.org/html/rfc7692
[server-report]: http://websockets.github.io/ws/autobahn/servers/
[session-parse-example]: ./examples/express-session-parse
[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent
[ws-server-options]:
https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback

2
node_modules/ws/browser.js generated vendored
View File

@@ -1,6 +1,6 @@
'use strict';
module.exports = function() {
module.exports = function () {
throw new Error(
'ws does not work in the browser. Browser clients must use the native ' +
'WebSocket object'

1
node_modules/ws/index.js generated vendored
View File

@@ -2,6 +2,7 @@
const WebSocket = require('./lib/websocket');
WebSocket.createWebSocketStream = require('./lib/stream');
WebSocket.Server = require('./lib/websocket-server');
WebSocket.Receiver = require('./lib/receiver');
WebSocket.Sender = require('./lib/sender');

33
node_modules/ws/lib/buffer-util.js generated vendored
View File

@@ -15,14 +15,16 @@ function concat(list, totalLength) {
if (list.length === 1) return list[0];
const target = Buffer.allocUnsafe(totalLength);
var offset = 0;
let offset = 0;
for (var i = 0; i < list.length; i++) {
for (let i = 0; i < list.length; i++) {
const buf = list[i];
buf.copy(target, offset);
target.set(buf, offset);
offset += buf.length;
}
if (offset < totalLength) return target.slice(0, offset);
return target;
}
@@ -37,7 +39,7 @@ function concat(list, totalLength) {
* @public
*/
function _mask(source, mask, output, offset, length) {
for (var i = 0; i < length; i++) {
for (let i = 0; i < length; i++) {
output[offset + i] = source[i] ^ mask[i & 3];
}
}
@@ -52,7 +54,7 @@ function _mask(source, mask, output, offset, length) {
function _unmask(buffer, mask) {
// Required until https://github.com/nodejs/node/issues/9006 is resolved.
const length = buffer.length;
for (var i = 0; i < length; i++) {
for (let i = 0; i < length; i++) {
buffer[i] ^= mask[i & 3];
}
}
@@ -85,12 +87,12 @@ function toBuffer(data) {
if (Buffer.isBuffer(data)) return data;
var buf;
let buf;
if (data instanceof ArrayBuffer) {
buf = Buffer.from(data);
} else if (ArrayBuffer.isView(data)) {
buf = viewToBuffer(data);
buf = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
} else {
buf = Buffer.from(data);
toBuffer.readOnly = false;
@@ -99,23 +101,6 @@ function toBuffer(data) {
return buf;
}
/**
* Converts an `ArrayBuffer` view into a buffer.
*
* @param {(DataView|TypedArray)} view The view to convert
* @return {Buffer} Converted view
* @private
*/
function viewToBuffer(view) {
const buf = Buffer.from(view.buffer);
if (view.byteLength !== view.buffer.byteLength) {
return buf.slice(view.byteOffset, view.byteOffset + view.byteLength);
}
return buf;
}
try {
const bufferUtil = require('bufferutil');
const bu = bufferUtil.BufferUtil || bufferUtil;

39
node_modules/ws/lib/event-target.js generated vendored
View File

@@ -109,11 +109,16 @@ const EventTarget = {
/**
* Register an event listener.
*
* @param {String} method A string representing the event type to listen for
* @param {String} type A string representing the event type to listen for
* @param {Function} listener The listener to add
* @param {Object} options An options object specifies characteristics about
* the event listener
* @param {Boolean} options.once A `Boolean`` indicating that the listener
* should be invoked at most once after being added. If `true`, the
* listener would be automatically removed when invoked.
* @public
*/
addEventListener(method, listener) {
addEventListener(type, listener, options) {
if (typeof listener !== 'function') return;
function onMessage(data) {
@@ -132,36 +137,38 @@ const EventTarget = {
listener.call(this, new OpenEvent(this));
}
if (method === 'message') {
const method = options && options.once ? 'once' : 'on';
if (type === 'message') {
onMessage._listener = listener;
this.on(method, onMessage);
} else if (method === 'close') {
this[method](type, onMessage);
} else if (type === 'close') {
onClose._listener = listener;
this.on(method, onClose);
} else if (method === 'error') {
this[method](type, onClose);
} else if (type === 'error') {
onError._listener = listener;
this.on(method, onError);
} else if (method === 'open') {
this[method](type, onError);
} else if (type === 'open') {
onOpen._listener = listener;
this.on(method, onOpen);
this[method](type, onOpen);
} else {
this.on(method, listener);
this[method](type, listener);
}
},
/**
* Remove an event listener.
*
* @param {String} method A string representing the event type to remove
* @param {String} type A string representing the event type to remove
* @param {Function} listener The listener to remove
* @public
*/
removeEventListener(method, listener) {
const listeners = this.listeners(method);
removeEventListener(type, listener) {
const listeners = this.listeners(type);
for (var i = 0; i < listeners.length; i++) {
for (let i = 0; i < listeners.length; i++) {
if (listeners[i] === listener || listeners[i]._listener === listener) {
this.removeListener(method, listeners[i]);
this.removeListener(type, listeners[i]);
}
}
}

39
node_modules/ws/lib/extension.js generated vendored
View File

@@ -34,8 +34,8 @@ const tokenChars = [
* @private
*/
function push(dest, name, elem) {
if (Object.prototype.hasOwnProperty.call(dest, name)) dest[name].push(elem);
else dest[name] = [elem];
if (dest[name] === undefined) dest[name] = [elem];
else dest[name].push(elem);
}
/**
@@ -46,20 +46,21 @@ function push(dest, name, elem) {
* @public
*/
function parse(header) {
const offers = {};
const offers = Object.create(null);
if (header === undefined || header === '') return offers;
var params = {};
var mustUnescape = false;
var isEscaping = false;
var inQuotes = false;
var extensionName;
var paramName;
var start = -1;
var end = -1;
let params = Object.create(null);
let mustUnescape = false;
let isEscaping = false;
let inQuotes = false;
let extensionName;
let paramName;
let start = -1;
let end = -1;
let i = 0;
for (var i = 0; i < header.length; i++) {
for (; i < header.length; i++) {
const code = header.charCodeAt(i);
if (extensionName === undefined) {
@@ -76,7 +77,7 @@ function parse(header) {
const name = header.slice(start, end);
if (code === 0x2c) {
push(offers, name, params);
params = {};
params = Object.create(null);
} else {
extensionName = name;
}
@@ -99,7 +100,7 @@ function parse(header) {
push(params, header.slice(start, end), true);
if (code === 0x2c) {
push(offers, extensionName, params);
params = {};
params = Object.create(null);
extensionName = undefined;
}
@@ -146,7 +147,7 @@ function parse(header) {
}
if (end === -1) end = i;
var value = header.slice(start, end);
let value = header.slice(start, end);
if (mustUnescape) {
value = value.replace(/\\/g, '');
mustUnescape = false;
@@ -154,7 +155,7 @@ function parse(header) {
push(params, paramName, value);
if (code === 0x2c) {
push(offers, extensionName, params);
params = {};
params = Object.create(null);
extensionName = undefined;
}
@@ -173,7 +174,7 @@ function parse(header) {
if (end === -1) end = i;
const token = header.slice(start, end);
if (extensionName === undefined) {
push(offers, token, {});
push(offers, token, params);
} else {
if (paramName === undefined) {
push(params, token, true);
@@ -198,14 +199,14 @@ function parse(header) {
function format(extensions) {
return Object.keys(extensions)
.map((extension) => {
var configurations = extensions[extension];
let configurations = extensions[extension];
if (!Array.isArray(configurations)) configurations = [configurations];
return configurations
.map((params) => {
return [extension]
.concat(
Object.keys(params).map((k) => {
var values = params[k];
let values = params[k];
if (!Array.isArray(values)) values = [values];
return values
.map((v) => (v === true ? k : `${k}=${v}`))

54
node_modules/ws/lib/limiter.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
'use strict';
const kDone = Symbol('kDone');
const kRun = Symbol('kRun');
/**
* A very simple job queue with adjustable concurrency. Adapted from
* https://github.com/STRML/async-limiter
*/
class Limiter {
/**
* Creates a new `Limiter`.
*
* @param {Number} concurrency The maximum number of jobs allowed to run
* concurrently
*/
constructor(concurrency) {
this[kDone] = () => {
this.pending--;
this[kRun]();
};
this.concurrency = concurrency || Infinity;
this.jobs = [];
this.pending = 0;
}
/**
* Adds a job to the queue.
*
* @public
*/
add(job) {
this.jobs.push(job);
this[kRun]();
}
/**
* Removes a job from the queue and runs it if possible.
*
* @private
*/
[kRun]() {
if (this.pending === this.concurrency) return;
if (this.jobs.length) {
const job = this.jobs.shift();
this.pending++;
job(this[kDone]);
}
}
}
module.exports = Limiter;

View File

@@ -1,14 +1,12 @@
'use strict';
const Limiter = require('async-limiter');
const zlib = require('zlib');
const bufferUtil = require('./buffer-util');
const Limiter = require('./limiter');
const { kStatusCode, NOOP } = require('./constants');
const TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);
const EMPTY_BLOCK = Buffer.from([0x00]);
const kPerMessageDeflate = Symbol('permessage-deflate');
const kTotalLength = Symbol('total-length');
const kCallback = Symbol('callback');
@@ -66,7 +64,7 @@ class PerMessageDeflate {
this._options.concurrencyLimit !== undefined
? this._options.concurrencyLimit
: 10;
zlibLimiter = new Limiter({ concurrency });
zlibLimiter = new Limiter(concurrency);
}
}
@@ -133,8 +131,18 @@ class PerMessageDeflate {
}
if (this._deflate) {
const callback = this._deflate[kCallback];
this._deflate.close();
this._deflate = null;
if (callback) {
callback(
new Error(
'The deflate stream was closed while data was being processed'
)
);
}
}
}
@@ -233,7 +241,7 @@ class PerMessageDeflate {
normalizeParams(configurations) {
configurations.forEach((params) => {
Object.keys(params).forEach((key) => {
var value = params[key];
let value = params[key];
if (value.length > 1) {
throw new Error(`Parameter "${key}" must have only a single value`);
@@ -284,7 +292,7 @@ class PerMessageDeflate {
}
/**
* Decompress data. Concurrency limited by async-limiter.
* Decompress data. Concurrency limited.
*
* @param {Buffer} data Compressed data
* @param {Boolean} fin Specifies whether or not this is the last fragment
@@ -292,7 +300,7 @@ class PerMessageDeflate {
* @public
*/
decompress(data, fin, callback) {
zlibLimiter.push((done) => {
zlibLimiter.add((done) => {
this._decompress(data, fin, (err, result) => {
done();
callback(err, result);
@@ -301,7 +309,7 @@ class PerMessageDeflate {
}
/**
* Compress data. Concurrency limited by async-limiter.
* Compress data. Concurrency limited.
*
* @param {Buffer} data Data to compress
* @param {Boolean} fin Specifies whether or not this is the last fragment
@@ -309,7 +317,7 @@ class PerMessageDeflate {
* @public
*/
compress(data, fin, callback) {
zlibLimiter.push((done) => {
zlibLimiter.add((done) => {
this._compress(data, fin, (err, result) => {
done();
callback(err, result);
@@ -335,9 +343,10 @@ class PerMessageDeflate {
? zlib.Z_DEFAULT_WINDOWBITS
: this.params[key];
this._inflate = zlib.createInflateRaw(
Object.assign({}, this._options.zlibInflateOptions, { windowBits })
);
this._inflate = zlib.createInflateRaw({
...this._options.zlibInflateOptions,
windowBits
});
this._inflate[kPerMessageDeflate] = this;
this._inflate[kTotalLength] = 0;
this._inflate[kBuffers] = [];
@@ -386,11 +395,6 @@ class PerMessageDeflate {
* @private
*/
_compress(data, fin, callback) {
if (!data || data.length === 0) {
process.nextTick(callback, null, EMPTY_BLOCK);
return;
}
const endpoint = this._isServer ? 'server' : 'client';
if (!this._deflate) {
@@ -400,9 +404,10 @@ class PerMessageDeflate {
? zlib.Z_DEFAULT_WINDOWBITS
: this.params[key];
this._deflate = zlib.createDeflateRaw(
Object.assign({}, this._options.zlibDeflateOptions, { windowBits })
);
this._deflate = zlib.createDeflateRaw({
...this._options.zlibDeflateOptions,
windowBits
});
this._deflate[kTotalLength] = 0;
this._deflate[kBuffers] = [];
@@ -417,25 +422,30 @@ class PerMessageDeflate {
this._deflate.on('data', deflateOnData);
}
this._deflate[kCallback] = callback;
this._deflate.write(data);
this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {
if (!this._deflate) {
//
// This `if` statement is only needed for Node.js < 10.0.0 because as of
// commit https://github.com/nodejs/node/commit/5e3f5164, the flush
// callback is no longer called if the deflate stream is closed while
// data is being processed.
// The deflate stream was closed while data was being processed.
//
return;
}
var data = bufferUtil.concat(
let data = bufferUtil.concat(
this._deflate[kBuffers],
this._deflate[kTotalLength]
);
if (fin) data = data.slice(0, data.length - 4);
//
// Ensure that the callback will not be called again in
// `PerMessageDeflate#cleanup()`.
//
this._deflate[kCallback] = null;
if (fin && this.params[`${endpoint}_no_context_takeover`]) {
this._deflate.close();
this._deflate = null;

27
node_modules/ws/lib/receiver.js generated vendored
View File

@@ -30,14 +30,17 @@ class Receiver extends Writable {
*
* @param {String} binaryType The type for binary data
* @param {Object} extensions An object containing the negotiated extensions
* @param {Boolean} isServer Specifies whether to operate in client or server
* mode
* @param {Number} maxPayload The maximum allowed message length
*/
constructor(binaryType, extensions, maxPayload) {
constructor(binaryType, extensions, isServer, maxPayload) {
super();
this._binaryType = binaryType || BINARY_TYPES[0];
this[kWebSocket] = undefined;
this._extensions = extensions || {};
this._isServer = !!isServer;
this._maxPayload = maxPayload | 0;
this._bufferedBytes = 0;
@@ -65,6 +68,7 @@ class Receiver extends Writable {
* @param {Buffer} chunk The chunk of data to write
* @param {String} encoding The character encoding of `chunk`
* @param {Function} cb Callback
* @private
*/
_write(chunk, encoding, cb) {
if (this._opcode === 0x08 && this._state == GET_INFO) return cb();
@@ -96,11 +100,12 @@ class Receiver extends Writable {
do {
const buf = this._buffers[0];
const offset = dst.length - n;
if (n >= buf.length) {
this._buffers.shift().copy(dst, dst.length - n);
dst.set(this._buffers.shift(), offset);
} else {
buf.copy(dst, dst.length - n, 0, n);
dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);
this._buffers[0] = buf.slice(n);
}
@@ -117,7 +122,7 @@ class Receiver extends Writable {
* @private
*/
startLoop(cb) {
var err;
let err;
this._loop = true;
do {
@@ -224,6 +229,16 @@ class Receiver extends Writable {
if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
this._masked = (buf[1] & 0x80) === 0x80;
if (this._isServer) {
if (!this._masked) {
this._loop = false;
return error(RangeError, 'MASK must be set', true, 1002);
}
} else if (this._masked) {
this._loop = false;
return error(RangeError, 'MASK must be clear', true, 1002);
}
if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;
else return this.haveLength();
@@ -320,7 +335,7 @@ class Receiver extends Writable {
* @private
*/
getData(cb) {
var data = EMPTY_BUFFER;
let data = EMPTY_BUFFER;
if (this._payloadLength) {
if (this._bufferedBytes < this._payloadLength) {
@@ -400,7 +415,7 @@ class Receiver extends Writable {
this._fragments = [];
if (this._opcode === 2) {
var data;
let data;
if (this._binaryType === 'nodebuffer') {
data = concat(fragments, messageLength);

56
node_modules/ws/lib/sender.js generated vendored
View File

@@ -1,12 +1,14 @@
'use strict';
const { randomBytes } = require('crypto');
const { randomFillSync } = require('crypto');
const PerMessageDeflate = require('./permessage-deflate');
const { EMPTY_BUFFER } = require('./constants');
const { isValidStatusCode } = require('./validation');
const { mask: applyMask, toBuffer } = require('./buffer-util');
const mask = Buffer.alloc(4);
/**
* HyBi Sender implementation.
*/
@@ -44,8 +46,8 @@ class Sender {
*/
static frame(data, options) {
const merge = options.mask && options.readOnly;
var offset = options.mask ? 6 : 2;
var payloadLength = data.length;
let offset = options.mask ? 6 : 2;
let payloadLength = data.length;
if (data.length >= 65536) {
offset += 8;
@@ -71,7 +73,7 @@ class Sender {
if (!options.mask) return [target, data];
const mask = randomBytes(4);
randomFillSync(mask, 0, 4);
target[1] |= 0x80;
target[offset - 4] = mask[0];
@@ -98,7 +100,7 @@ class Sender {
* @public
*/
close(code, data, mask, cb) {
var buf;
let buf;
if (code === undefined) {
buf = EMPTY_BUFFER;
@@ -108,7 +110,13 @@ class Sender {
buf = Buffer.allocUnsafe(2);
buf.writeUInt16BE(code, 0);
} else {
buf = Buffer.allocUnsafe(2 + Buffer.byteLength(data));
const length = Buffer.byteLength(data);
if (length > 123) {
throw new RangeError('The message must not be greater than 123 bytes');
}
buf = Buffer.allocUnsafe(2 + length);
buf.writeUInt16BE(code, 0);
buf.write(data, 2);
}
@@ -152,6 +160,10 @@ class Sender {
ping(data, mask, cb) {
const buf = toBuffer(data);
if (buf.length > 125) {
throw new RangeError('The data size must not be greater than 125 bytes');
}
if (this._deflating) {
this.enqueue([this.doPing, buf, mask, toBuffer.readOnly, cb]);
} else {
@@ -162,7 +174,7 @@ class Sender {
/**
* Frames and sends a ping message.
*
* @param {*} data The message to send
* @param {Buffer} data The message to send
* @param {Boolean} mask Specifies whether or not to mask `data`
* @param {Boolean} readOnly Specifies whether `data` can be modified
* @param {Function} cb Callback
@@ -192,6 +204,10 @@ class Sender {
pong(data, mask, cb) {
const buf = toBuffer(data);
if (buf.length > 125) {
throw new RangeError('The data size must not be greater than 125 bytes');
}
if (this._deflating) {
this.enqueue([this.doPong, buf, mask, toBuffer.readOnly, cb]);
} else {
@@ -202,7 +218,7 @@ class Sender {
/**
* Frames and sends a pong message.
*
* @param {*} data The message to send
* @param {Buffer} data The message to send
* @param {Boolean} mask Specifies whether or not to mask `data`
* @param {Boolean} readOnly Specifies whether `data` can be modified
* @param {Function} cb Callback
@@ -236,8 +252,8 @@ class Sender {
send(data, options, cb) {
const buf = toBuffer(data);
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
var opcode = options.binary ? 2 : 1;
var rsv1 = options.compress;
let opcode = options.binary ? 2 : 1;
let rsv1 = options.compress;
if (this._firstFragment) {
this._firstFragment = false;
@@ -302,8 +318,26 @@ class Sender {
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
this._bufferedBytes += data.length;
this._deflating = true;
perMessageDeflate.compress(data, options.fin, (_, buf) => {
if (this._socket.destroyed) {
const err = new Error(
'The socket was closed while data was being compressed'
);
if (typeof cb === 'function') cb(err);
for (let i = 0; i < this._queue.length; i++) {
const callback = this._queue[i][4];
if (typeof callback === 'function') callback(err);
}
return;
}
this._bufferedBytes -= data.length;
this._deflating = false;
options.readOnly = false;
this.sendFrame(Sender.frame(buf, options), cb);
@@ -321,7 +355,7 @@ class Sender {
const params = this._queue.shift();
this._bufferedBytes -= params[1].length;
params[0].apply(this, params.slice(1));
Reflect.apply(params[0], this, params.slice(1));
}
}

164
node_modules/ws/lib/stream.js generated vendored Normal file
View File

@@ -0,0 +1,164 @@
'use strict';
const { Duplex } = require('stream');
/**
* Emits the `'close'` event on a stream.
*
* @param {stream.Duplex} The stream.
* @private
*/
function emitClose(stream) {
stream.emit('close');
}
/**
* The listener of the `'end'` event.
*
* @private
*/
function duplexOnEnd() {
if (!this.destroyed && this._writableState.finished) {
this.destroy();
}
}
/**
* The listener of the `'error'` event.
*
* @private
*/
function duplexOnError(err) {
this.removeListener('error', duplexOnError);
this.destroy();
if (this.listenerCount('error') === 0) {
// Do not suppress the throwing behavior.
this.emit('error', err);
}
}
/**
* Wraps a `WebSocket` in a duplex stream.
*
* @param {WebSocket} ws The `WebSocket` to wrap
* @param {Object} options The options for the `Duplex` constructor
* @return {stream.Duplex} The duplex stream
* @public
*/
function createWebSocketStream(ws, options) {
let resumeOnReceiverDrain = true;
function receiverOnDrain() {
if (resumeOnReceiverDrain) ws._socket.resume();
}
if (ws.readyState === ws.CONNECTING) {
ws.once('open', function open() {
ws._receiver.removeAllListeners('drain');
ws._receiver.on('drain', receiverOnDrain);
});
} else {
ws._receiver.removeAllListeners('drain');
ws._receiver.on('drain', receiverOnDrain);
}
const duplex = new Duplex({
...options,
autoDestroy: false,
emitClose: false,
objectMode: false,
writableObjectMode: false
});
ws.on('message', function message(msg) {
if (!duplex.push(msg)) {
resumeOnReceiverDrain = false;
ws._socket.pause();
}
});
ws.once('error', function error(err) {
if (duplex.destroyed) return;
duplex.destroy(err);
});
ws.once('close', function close() {
if (duplex.destroyed) return;
duplex.push(null);
});
duplex._destroy = function (err, callback) {
if (ws.readyState === ws.CLOSED) {
callback(err);
process.nextTick(emitClose, duplex);
return;
}
let called = false;
ws.once('error', function error(err) {
called = true;
callback(err);
});
ws.once('close', function close() {
if (!called) callback(err);
process.nextTick(emitClose, duplex);
});
ws.terminate();
};
duplex._final = function (callback) {
if (ws.readyState === ws.CONNECTING) {
ws.once('open', function open() {
duplex._final(callback);
});
return;
}
// If the value of the `_socket` property is `null` it means that `ws` is a
// client websocket and the handshake failed. In fact, when this happens, a
// socket is never assigned to the websocket. Wait for the `'error'` event
// that will be emitted by the websocket.
if (ws._socket === null) return;
if (ws._socket._writableState.finished) {
callback();
if (duplex._readableState.endEmitted) duplex.destroy();
} else {
ws._socket.once('finish', function finish() {
// `duplex` is not destroyed here because the `'end'` event will be
// emitted on `duplex` after this `'finish'` event. The EOF signaling
// `null` chunk is, in fact, pushed when the websocket emits `'close'`.
callback();
});
ws.close();
}
};
duplex._read = function () {
if (ws.readyState === ws.OPEN && !resumeOnReceiverDrain) {
resumeOnReceiverDrain = true;
if (!ws._receiver._writableState.needDrain) ws._socket.resume();
}
};
duplex._write = function (chunk, encoding, callback) {
if (ws.readyState === ws.CONNECTING) {
ws.once('open', function open() {
duplex._write(chunk, encoding, callback);
});
return;
}
ws.send(chunk, callback);
};
duplex.on('end', duplexOnEnd);
duplex.on('error', duplexOnError);
return duplex;
}
module.exports = createWebSocketStream;

2
node_modules/ws/lib/validation.js generated vendored
View File

@@ -21,7 +21,7 @@ try {
exports.isValidStatusCode = (code) => {
return (
(code >= 1000 &&
code <= 1013 &&
code <= 1014 &&
code !== 1004 &&
code !== 1005 &&
code !== 1006) ||

View File

@@ -1,13 +1,13 @@
'use strict';
const EventEmitter = require('events');
const crypto = require('crypto');
const http = require('http');
const { createHash } = require('crypto');
const { createServer, STATUS_CODES } = require('http');
const PerMessageDeflate = require('./permessage-deflate');
const extension = require('./extension');
const WebSocket = require('./websocket');
const { GUID } = require('./constants');
const { format, parse } = require('./extension');
const { GUID, kWebSocket } = require('./constants');
const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
@@ -25,7 +25,7 @@ class WebSocketServer extends EventEmitter {
* connections
* @param {Boolean} options.clientTracking Specifies whether or not to track
* clients
* @param {Function} options.handleProtocols An hook to handle protocols
* @param {Function} options.handleProtocols A hook to handle protocols
* @param {String} options.host The hostname where to bind the server
* @param {Number} options.maxPayload The maximum allowed message size
* @param {Boolean} options.noServer Enable no server mode
@@ -34,28 +34,26 @@ class WebSocketServer extends EventEmitter {
* permessage-deflate
* @param {Number} options.port The port where to bind the server
* @param {http.Server} options.server A pre-created HTTP/S server to use
* @param {Function} options.verifyClient An hook to reject connections
* @param {Function} options.verifyClient A hook to reject connections
* @param {Function} callback A listener for the `listening` event
*/
constructor(options, callback) {
super();
options = Object.assign(
{
maxPayload: 100 * 1024 * 1024,
perMessageDeflate: false,
handleProtocols: null,
clientTracking: true,
verifyClient: null,
noServer: false,
backlog: null, // use default (511 as implemented in net.js)
server: null,
host: null,
path: null,
port: null
},
options
);
options = {
maxPayload: 100 * 1024 * 1024,
perMessageDeflate: false,
handleProtocols: null,
clientTracking: true,
verifyClient: null,
noServer: false,
backlog: null, // use default (511 as implemented in net.js)
server: null,
host: null,
path: null,
port: null,
...options
};
if (options.port == null && !options.server && !options.noServer) {
throw new TypeError(
@@ -64,8 +62,8 @@ class WebSocketServer extends EventEmitter {
}
if (options.port != null) {
this._server = http.createServer((req, res) => {
const body = http.STATUS_CODES[426];
this._server = createServer((req, res) => {
const body = STATUS_CODES[426];
res.writeHead(426, {
'Content-Length': body.length,
@@ -208,7 +206,7 @@ class WebSocketServer extends EventEmitter {
);
try {
const offers = extension.parse(req.headers['sec-websocket-extensions']);
const offers = parse(req.headers['sec-websocket-extensions']);
if (offers[PerMessageDeflate.extensionName]) {
perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);
@@ -256,6 +254,7 @@ class WebSocketServer extends EventEmitter {
* @param {net.Socket} socket The network socket between the server and client
* @param {Buffer} head The first packet of the upgraded stream
* @param {Function} cb Callback
* @throws {Error} If called more than once with the same socket
* @private
*/
completeUpgrade(key, extensions, req, socket, head, cb) {
@@ -264,8 +263,14 @@ class WebSocketServer extends EventEmitter {
//
if (!socket.readable || !socket.writable) return socket.destroy();
const digest = crypto
.createHash('sha1')
if (socket[kWebSocket]) {
throw new Error(
'server.handleUpgrade() was called more than once with the same ' +
'socket, possibly due to a misconfiguration'
);
}
const digest = createHash('sha1')
.update(key + GUID)
.digest('base64');
@@ -277,7 +282,7 @@ class WebSocketServer extends EventEmitter {
];
const ws = new WebSocket(null);
var protocol = req.headers['sec-websocket-protocol'];
let protocol = req.headers['sec-websocket-protocol'];
if (protocol) {
protocol = protocol.trim().split(/ *, */);
@@ -299,7 +304,7 @@ class WebSocketServer extends EventEmitter {
if (extensions[PerMessageDeflate.extensionName]) {
const params = extensions[PerMessageDeflate.extensionName].params;
const value = extension.format({
const value = format({
[PerMessageDeflate.extensionName]: [params]
});
headers.push(`Sec-WebSocket-Extensions: ${value}`);
@@ -376,18 +381,16 @@ function socketOnError() {
*/
function abortHandshake(socket, code, message, headers) {
if (socket.writable) {
message = message || http.STATUS_CODES[code];
headers = Object.assign(
{
Connection: 'close',
'Content-type': 'text/html',
'Content-Length': Buffer.byteLength(message)
},
headers
);
message = message || STATUS_CODES[code];
headers = {
Connection: 'close',
'Content-Type': 'text/html',
'Content-Length': Buffer.byteLength(message),
...headers
};
socket.write(
`HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` +
`HTTP/1.1 ${code} ${STATUS_CODES[code]}\r\n` +
Object.keys(headers)
.map((h) => `${h}: ${headers[h]}`)
.join('\r\n') +

252
node_modules/ws/lib/websocket.js generated vendored
View File

@@ -1,16 +1,14 @@
'use strict';
const EventEmitter = require('events');
const crypto = require('crypto');
const https = require('https');
const http = require('http');
const net = require('net');
const tls = require('tls');
const url = require('url');
const { randomBytes, createHash } = require('crypto');
const { URL } = require('url');
const PerMessageDeflate = require('./permessage-deflate');
const EventTarget = require('./event-target');
const extension = require('./extension');
const Receiver = require('./receiver');
const Sender = require('./sender');
const {
@@ -21,6 +19,9 @@ const {
kWebSocket,
NOOP
} = require('./constants');
const { addEventListener, removeEventListener } = require('./event-target');
const { format, parse } = require('./extension');
const { toBuffer } = require('./buffer-util');
const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
const protocolVersions = [8, 13];
@@ -35,7 +36,7 @@ class WebSocket extends EventEmitter {
/**
* Create a new `WebSocket`.
*
* @param {(String|url.Url|url.URL)} address The URL to which to connect
* @param {(String|url.URL)} address The URL to which to connect
* @param {(String|String[])} protocols The subprotocols
* @param {Object} options Connection options
*/
@@ -57,6 +58,7 @@ class WebSocket extends EventEmitter {
this._socket = null;
if (address !== null) {
this._bufferedAmount = 0;
this._isServer = false;
this._redirects = 0;
@@ -112,12 +114,9 @@ class WebSocket extends EventEmitter {
* @type {Number}
*/
get bufferedAmount() {
if (!this._socket) return 0;
if (!this._socket) return this._bufferedAmount;
//
// `socket.bufferSize` is `undefined` if the socket is closed.
//
return (this._socket.bufferSize || 0) + this._sender._bufferedBytes;
return this._socket._writableState.length + this._sender._bufferedBytes;
}
/**
@@ -139,6 +138,7 @@ class WebSocket extends EventEmitter {
const receiver = new Receiver(
this._binaryType,
this._extensions,
this._isServer,
maxPayload
);
@@ -176,9 +176,8 @@ class WebSocket extends EventEmitter {
* @private
*/
emitClose() {
this.readyState = WebSocket.CLOSED;
if (!this._socket) {
this.readyState = WebSocket.CLOSED;
this.emit('close', this._closeCode, this._closeMessage);
return;
}
@@ -188,6 +187,7 @@ class WebSocket extends EventEmitter {
}
this._receiver.removeAllListeners();
this.readyState = WebSocket.CLOSED;
this.emit('close', this._closeCode, this._closeMessage);
}
@@ -252,6 +252,10 @@ class WebSocket extends EventEmitter {
* @public
*/
ping(data, mask, cb) {
if (this.readyState === WebSocket.CONNECTING) {
throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');
}
if (typeof data === 'function') {
cb = data;
data = mask = undefined;
@@ -260,17 +264,13 @@ class WebSocket extends EventEmitter {
mask = undefined;
}
if (this.readyState !== WebSocket.OPEN) {
const err = new Error(
`WebSocket is not open: readyState ${this.readyState} ` +
`(${readyStates[this.readyState]})`
);
if (typeof data === 'number') data = data.toString();
if (cb) return cb(err);
throw err;
if (this.readyState !== WebSocket.OPEN) {
sendAfterClose(this, data, cb);
return;
}
if (typeof data === 'number') data = data.toString();
if (mask === undefined) mask = !this._isServer;
this._sender.ping(data || EMPTY_BUFFER, mask, cb);
}
@@ -284,6 +284,10 @@ class WebSocket extends EventEmitter {
* @public
*/
pong(data, mask, cb) {
if (this.readyState === WebSocket.CONNECTING) {
throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');
}
if (typeof data === 'function') {
cb = data;
data = mask = undefined;
@@ -292,17 +296,13 @@ class WebSocket extends EventEmitter {
mask = undefined;
}
if (this.readyState !== WebSocket.OPEN) {
const err = new Error(
`WebSocket is not open: readyState ${this.readyState} ` +
`(${readyStates[this.readyState]})`
);
if (typeof data === 'number') data = data.toString();
if (cb) return cb(err);
throw err;
if (this.readyState !== WebSocket.OPEN) {
sendAfterClose(this, data, cb);
return;
}
if (typeof data === 'number') data = data.toString();
if (mask === undefined) mask = !this._isServer;
this._sender.pong(data || EMPTY_BUFFER, mask, cb);
}
@@ -312,7 +312,8 @@ class WebSocket extends EventEmitter {
*
* @param {*} data The message to send
* @param {Object} options Options object
* @param {Boolean} options.compress Specifies whether or not to compress `data`
* @param {Boolean} options.compress Specifies whether or not to compress
* `data`
* @param {Boolean} options.binary Specifies whether `data` is binary or text
* @param {Boolean} options.fin Specifies whether the fragment is the last one
* @param {Boolean} options.mask Specifies whether or not to mask `data`
@@ -320,32 +321,29 @@ class WebSocket extends EventEmitter {
* @public
*/
send(data, options, cb) {
if (this.readyState === WebSocket.CONNECTING) {
throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');
}
if (typeof options === 'function') {
cb = options;
options = {};
}
if (this.readyState !== WebSocket.OPEN) {
const err = new Error(
`WebSocket is not open: readyState ${this.readyState} ` +
`(${readyStates[this.readyState]})`
);
if (cb) return cb(err);
throw err;
}
if (typeof data === 'number') data = data.toString();
const opts = Object.assign(
{
binary: typeof data !== 'string',
mask: !this._isServer,
compress: true,
fin: true
},
options
);
if (this.readyState !== WebSocket.OPEN) {
sendAfterClose(this, data, cb);
return;
}
const opts = {
binary: typeof data !== 'string',
mask: !this._isServer,
compress: true,
fin: true,
...options
};
if (!this._extensions[PerMessageDeflate.extensionName]) {
opts.compress = false;
@@ -391,7 +389,7 @@ readyStates.forEach((readyState, i) => {
*/
get() {
const listeners = this.listeners(method);
for (var i = 0; i < listeners.length; i++) {
for (let i = 0; i < listeners.length; i++) {
if (listeners[i]._listener) return listeners[i]._listener;
}
@@ -405,7 +403,7 @@ readyStates.forEach((readyState, i) => {
*/
set(listener) {
const listeners = this.listeners(method);
for (var i = 0; i < listeners.length; i++) {
for (let i = 0; i < listeners.length; i++) {
//
// Remove only the listeners added via `addEventListener`.
//
@@ -416,8 +414,8 @@ readyStates.forEach((readyState, i) => {
});
});
WebSocket.prototype.addEventListener = EventTarget.addEventListener;
WebSocket.prototype.removeEventListener = EventTarget.removeEventListener;
WebSocket.prototype.addEventListener = addEventListener;
WebSocket.prototype.removeEventListener = removeEventListener;
module.exports = WebSocket;
@@ -425,7 +423,7 @@ module.exports = WebSocket;
* Initialize a WebSocket client.
*
* @param {WebSocket} websocket The client to initialize
* @param {(String|url.Url|url.URL)} address The URL to which to connect
* @param {(String|url.URL)} address The URL to which to connect
* @param {String} protocols The subprotocols
* @param {Object} options Connection options
* @param {(Boolean|Object)} options.perMessageDeflate Enable/disable
@@ -442,28 +440,23 @@ module.exports = WebSocket;
* @private
*/
function initAsClient(websocket, address, protocols, options) {
const opts = Object.assign(
{
protocolVersion: protocolVersions[1],
maxPayload: 100 * 1024 * 1024,
perMessageDeflate: true,
followRedirects: false,
maxRedirects: 10
},
options,
{
createConnection: undefined,
socketPath: undefined,
hostname: undefined,
protocol: undefined,
timeout: undefined,
method: undefined,
auth: undefined,
host: undefined,
path: undefined,
port: undefined
}
);
const opts = {
protocolVersion: protocolVersions[1],
maxPayload: 100 * 1024 * 1024,
perMessageDeflate: true,
followRedirects: false,
maxRedirects: 10,
...options,
createConnection: undefined,
socketPath: undefined,
hostname: undefined,
protocol: undefined,
timeout: undefined,
method: undefined,
host: undefined,
path: undefined,
port: undefined
};
if (!protocolVersions.includes(opts.protocolVersion)) {
throw new RangeError(
@@ -472,16 +465,13 @@ function initAsClient(websocket, address, protocols, options) {
);
}
var parsedUrl;
let parsedUrl;
if (typeof address === 'object' && address.href !== undefined) {
if (address instanceof URL) {
parsedUrl = address;
websocket.url = address.href;
} else {
//
// The WHATWG URL constructor is not available on Node.js < 6.13.0
//
parsedUrl = url.URL ? new url.URL(address) : url.parse(address);
parsedUrl = new URL(address);
websocket.url = address;
}
@@ -494,12 +484,9 @@ function initAsClient(websocket, address, protocols, options) {
const isSecure =
parsedUrl.protocol === 'wss:' || parsedUrl.protocol === 'https:';
const defaultPort = isSecure ? 443 : 80;
const key = crypto.randomBytes(16).toString('base64');
const key = randomBytes(16).toString('base64');
const get = isSecure ? https.get : http.get;
const path = parsedUrl.search
? `${parsedUrl.pathname || '/'}${parsedUrl.search}`
: parsedUrl.pathname || '/';
var perMessageDeflate;
let perMessageDeflate;
opts.createConnection = isSecure ? tlsConnect : netConnect;
opts.defaultPort = opts.defaultPort || defaultPort;
@@ -507,16 +494,14 @@ function initAsClient(websocket, address, protocols, options) {
opts.host = parsedUrl.hostname.startsWith('[')
? parsedUrl.hostname.slice(1, -1)
: parsedUrl.hostname;
opts.headers = Object.assign(
{
'Sec-WebSocket-Version': opts.protocolVersion,
'Sec-WebSocket-Key': key,
Connection: 'Upgrade',
Upgrade: 'websocket'
},
opts.headers
);
opts.path = path;
opts.headers = {
'Sec-WebSocket-Version': opts.protocolVersion,
'Sec-WebSocket-Key': key,
Connection: 'Upgrade',
Upgrade: 'websocket',
...opts.headers
};
opts.path = parsedUrl.pathname + parsedUrl.search;
opts.timeout = opts.handshakeTimeout;
if (opts.perMessageDeflate) {
@@ -525,7 +510,7 @@ function initAsClient(websocket, address, protocols, options) {
false,
opts.maxPayload
);
opts.headers['Sec-WebSocket-Extensions'] = extension.format({
opts.headers['Sec-WebSocket-Extensions'] = format({
[PerMessageDeflate.extensionName]: perMessageDeflate.offer()
});
}
@@ -539,20 +524,18 @@ function initAsClient(websocket, address, protocols, options) {
opts.headers.Origin = opts.origin;
}
}
if (parsedUrl.auth) {
opts.auth = parsedUrl.auth;
} else if (parsedUrl.username || parsedUrl.password) {
if (parsedUrl.username || parsedUrl.password) {
opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
}
if (isUnixSocket) {
const parts = path.split(':');
const parts = opts.path.split(':');
opts.socketPath = parts[0];
opts.path = parts[1];
}
var req = (websocket._req = get(opts));
let req = (websocket._req = get(opts));
if (opts.timeout) {
req.on('timeout', () => {
@@ -586,9 +569,7 @@ function initAsClient(websocket, address, protocols, options) {
req.abort();
const addr = url.URL
? new url.URL(location, address)
: url.resolve(address, location);
const addr = new URL(location, address);
initAsClient(websocket, addr, protocols, options);
} else if (!websocket.emit('unexpected-response', req, res)) {
@@ -611,8 +592,7 @@ function initAsClient(websocket, address, protocols, options) {
req = websocket._req = null;
const digest = crypto
.createHash('sha1')
const digest = createHash('sha1')
.update(key + GUID)
.digest('base64');
@@ -623,7 +603,7 @@ function initAsClient(websocket, address, protocols, options) {
const serverProt = res.headers['sec-websocket-protocol'];
const protList = (protocols || '').split(/, */);
var protError;
let protError;
if (!protocols && serverProt) {
protError = 'Server sent a subprotocol but none was requested';
@@ -642,9 +622,7 @@ function initAsClient(websocket, address, protocols, options) {
if (perMessageDeflate) {
try {
const extensions = extension.parse(
res.headers['sec-websocket-extensions']
);
const extensions = parse(res.headers['sec-websocket-extensions']);
if (extensions[PerMessageDeflate.extensionName]) {
perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);
@@ -674,13 +652,7 @@ function initAsClient(websocket, address, protocols, options) {
* @private
*/
function netConnect(options) {
//
// Override `options.path` only if `options` is a copy of the original options
// object. This is always true on Node.js >= 8 but not on Node.js 6 where
// `options.socketPath` might be `undefined` even if the `socketPath` option
// was originally set.
//
if (options.protocolVersion) options.path = options.socketPath;
options.path = options.socketPath;
return net.connect(options);
}
@@ -693,7 +665,11 @@ function netConnect(options) {
*/
function tlsConnect(options) {
options.path = undefined;
options.servername = options.servername || options.host;
if (!options.servername && options.servername !== '') {
options.servername = options.host;
}
return tls.connect(options);
}
@@ -723,6 +699,38 @@ function abortHandshake(websocket, stream, message) {
}
}
/**
* Handle cases where the `ping()`, `pong()`, or `send()` methods are called
* when the `readyState` attribute is `CLOSING` or `CLOSED`.
*
* @param {WebSocket} websocket The WebSocket instance
* @param {*} data The data to send
* @param {Function} cb Callback
* @private
*/
function sendAfterClose(websocket, data, cb) {
if (data) {
const length = toBuffer(data).length;
//
// The `_bufferedAmount` property is used only when the peer is a client and
// the opening handshake fails. Under these circumstances, in fact, the
// `setSocket()` method is not called, so the `_socket` and `_sender`
// properties are set to `null`.
//
if (websocket._socket) websocket._sender._bufferedBytes += length;
else websocket._bufferedAmount += length;
}
if (cb) {
const err = new Error(
`WebSocket is not open: readyState ${websocket.readyState} ` +
`(${readyStates[websocket.readyState]})`
);
cb(err);
}
}
/**
* The listener of the `Receiver` `'conclude'` event.
*
@@ -890,6 +898,8 @@ function socketOnError() {
this.removeListener('error', socketOnError);
this.on('error', NOOP);
websocket.readyState = WebSocket.CLOSING;
this.destroy();
if (websocket) {
websocket.readyState = WebSocket.CLOSING;
this.destroy();
}
}

66
node_modules/ws/package.json generated vendored
View File

@@ -1,27 +1,27 @@
{
"_from": "ws@^6.1.2",
"_id": "ws@6.2.1",
"_from": "ws@^7.2.3",
"_id": "ws@7.3.1",
"_inBundle": false,
"_integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
"_integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==",
"_location": "/ws",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "ws@^6.1.2",
"raw": "ws@^7.2.3",
"name": "ws",
"escapedName": "ws",
"rawSpec": "^6.1.2",
"rawSpec": "^7.2.3",
"saveSpec": null,
"fetchSpec": "^6.1.2"
"fetchSpec": "^7.2.3"
},
"_requiredBy": [
"/jsdom"
],
"_resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
"_shasum": "442fdf0a47ed64f59b6a5d8ff130f4748ed524fb",
"_spec": "ws@^6.1.2",
"_where": "F:\\projects\\p\\minifyfromhtml\\node_modules\\jsdom",
"_resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
"_shasum": "d0547bf67f7ce4f12a72dfe31262c68d7dc551c8",
"_spec": "ws@^7.2.3",
"_where": "D:\\Projects\\minifyfromhtml\\node_modules\\jsdom",
"author": {
"name": "Einar Otto Stangvik",
"email": "einaros@gmail.com",
@@ -32,22 +32,22 @@
"url": "https://github.com/websockets/ws/issues"
},
"bundleDependencies": false,
"dependencies": {
"async-limiter": "~1.0.0"
},
"deprecated": false,
"description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js",
"devDependencies": {
"benchmark": "~2.1.4",
"bufferutil": "~4.0.0",
"coveralls": "~3.0.3",
"eslint": "~5.15.0",
"eslint-config-prettier": "~4.1.0",
"eslint-plugin-prettier": "~3.0.0",
"mocha": "~6.0.0",
"nyc": "~13.3.0",
"prettier": "~1.16.1",
"utf-8-validate": "~5.0.0"
"benchmark": "^2.1.4",
"bufferutil": "^4.0.1",
"coveralls": "^3.0.3",
"eslint": "^7.2.0",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-prettier": "^3.0.1",
"mocha": "^7.0.0",
"nyc": "^15.0.0",
"prettier": "^2.0.5",
"utf-8-validate": "^5.0.2"
},
"engines": {
"node": ">=8.3.0"
},
"files": [
"browser.js",
@@ -66,14 +66,26 @@
"license": "MIT",
"main": "index.js",
"name": "ws",
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/websockets/ws.git"
},
"scripts": {
"integration": "npm run lint && mocha test/*.integration.js",
"lint": "eslint --ignore-path .gitignore . && prettier --check --ignore-path .gitignore \"**/*.{json,md,yml}\"",
"test": "npm run lint && nyc --reporter=html --reporter=text mocha test/*.test.js"
"integration": "mocha --throw-deprecation test/*.integration.js",
"lint": "eslint --ignore-path .gitignore . && prettier --check --ignore-path .gitignore \"**/*.{json,md,yaml,yml}\"",
"test": "nyc --reporter=html --reporter=text mocha --throw-deprecation test/*.test.js"
},
"version": "6.2.1"
"version": "7.3.1"
}