Comparing version 6.2.1 to 7.0.0
@@ -18,5 +18,5 @@ 'use strict'; | ||
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]; | ||
@@ -41,3 +41,3 @@ buf.copy(target, offset); | ||
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]; | ||
@@ -57,3 +57,3 @@ } | ||
const length = buffer.length; | ||
for (var i = 0; i < length; i++) { | ||
for (let i = 0; i < length; i++) { | ||
buffer[i] ^= mask[i & 3]; | ||
@@ -91,3 +91,3 @@ } | ||
var buf; | ||
let buf; | ||
@@ -94,0 +94,0 @@ if (data instanceof ArrayBuffer) { |
@@ -162,3 +162,3 @@ 'use strict'; | ||
for (var i = 0; i < listeners.length; i++) { | ||
for (let i = 0; i < listeners.length; i++) { | ||
if (listeners[i] === listener || listeners[i]._listener === listener) { | ||
@@ -165,0 +165,0 @@ this.removeListener(method, listeners[i]); |
@@ -37,4 +37,4 @@ 'use strict'; | ||
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); | ||
} | ||
@@ -50,16 +50,17 @@ | ||
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); | ||
@@ -81,3 +82,3 @@ | ||
push(offers, name, params); | ||
params = {}; | ||
params = Object.create(null); | ||
} else { | ||
@@ -105,3 +106,3 @@ extensionName = name; | ||
push(offers, extensionName, params); | ||
params = {}; | ||
params = Object.create(null); | ||
extensionName = undefined; | ||
@@ -153,3 +154,3 @@ } | ||
if (end === -1) end = i; | ||
var value = header.slice(start, end); | ||
let value = header.slice(start, end); | ||
if (mustUnescape) { | ||
@@ -162,3 +163,3 @@ value = value.replace(/\\/g, ''); | ||
push(offers, extensionName, params); | ||
params = {}; | ||
params = Object.create(null); | ||
extensionName = undefined; | ||
@@ -182,3 +183,3 @@ } | ||
if (extensionName === undefined) { | ||
push(offers, token, {}); | ||
push(offers, token, params); | ||
} else { | ||
@@ -208,3 +209,3 @@ if (paramName === undefined) { | ||
.map((extension) => { | ||
var configurations = extensions[extension]; | ||
let configurations = extensions[extension]; | ||
if (!Array.isArray(configurations)) configurations = [configurations]; | ||
@@ -216,3 +217,3 @@ return configurations | ||
Object.keys(params).map((k) => { | ||
var values = params[k]; | ||
let values = params[k]; | ||
if (!Array.isArray(values)) values = [values]; | ||
@@ -219,0 +220,0 @@ return values |
@@ -236,3 +236,3 @@ 'use strict'; | ||
Object.keys(params).forEach((key) => { | ||
var value = params[key]; | ||
let value = params[key]; | ||
@@ -339,5 +339,6 @@ if (value.length > 1) { | ||
this._inflate = zlib.createInflateRaw( | ||
Object.assign({}, this._options.zlibInflateOptions, { windowBits }) | ||
); | ||
this._inflate = zlib.createInflateRaw({ | ||
...this._options.zlibInflateOptions, | ||
windowBits | ||
}); | ||
this._inflate[kPerMessageDeflate] = this; | ||
@@ -405,5 +406,6 @@ this._inflate[kTotalLength] = 0; | ||
this._deflate = zlib.createDeflateRaw( | ||
Object.assign({}, this._options.zlibDeflateOptions, { windowBits }) | ||
); | ||
this._deflate = zlib.createDeflateRaw({ | ||
...this._options.zlibDeflateOptions, | ||
windowBits | ||
}); | ||
@@ -435,3 +437,3 @@ this._deflate[kTotalLength] = 0; | ||
var data = bufferUtil.concat( | ||
let data = bufferUtil.concat( | ||
this._deflate[kBuffers], | ||
@@ -438,0 +440,0 @@ this._deflate[kTotalLength] |
@@ -120,3 +120,3 @@ 'use strict'; | ||
startLoop(cb) { | ||
var err; | ||
let err; | ||
this._loop = true; | ||
@@ -324,3 +324,3 @@ | ||
getData(cb) { | ||
var data = EMPTY_BUFFER; | ||
let data = EMPTY_BUFFER; | ||
@@ -405,3 +405,3 @@ if (this._payloadLength) { | ||
if (this._opcode === 2) { | ||
var data; | ||
let data; | ||
@@ -408,0 +408,0 @@ if (this._binaryType === 'nodebuffer') { |
'use strict'; | ||
const { randomBytes } = require('crypto'); | ||
const { randomFillSync } = require('crypto'); | ||
@@ -10,2 +10,4 @@ const PerMessageDeflate = require('./permessage-deflate'); | ||
const mask = Buffer.alloc(4); | ||
/** | ||
@@ -48,4 +50,4 @@ * HyBi Sender implementation. | ||
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; | ||
@@ -76,3 +78,3 @@ if (data.length >= 65536) { | ||
const mask = randomBytes(4); | ||
randomFillSync(mask, 0, 4); | ||
@@ -104,3 +106,3 @@ target[1] |= 0x80; | ||
close(code, data, mask, cb) { | ||
var buf; | ||
let buf; | ||
@@ -243,4 +245,4 @@ if (code === undefined) { | ||
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; | ||
@@ -329,3 +331,3 @@ if (this._firstFragment) { | ||
this._bufferedBytes -= params[1].length; | ||
params[0].apply(this, params.slice(1)); | ||
Reflect.apply(params[0], this, params.slice(1)); | ||
} | ||
@@ -332,0 +334,0 @@ } |
'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 { format, parse } = require('./extension'); | ||
const { GUID } = require('./constants'); | ||
@@ -43,18 +43,16 @@ | ||
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 | ||
}; | ||
@@ -68,4 +66,4 @@ if (options.port == null && !options.server && !options.noServer) { | ||
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]; | ||
@@ -213,3 +211,3 @@ res.writeHead(426, { | ||
try { | ||
const offers = extension.parse(req.headers['sec-websocket-extensions']); | ||
const offers = parse(req.headers['sec-websocket-extensions']); | ||
@@ -270,4 +268,3 @@ if (offers[PerMessageDeflate.extensionName]) { | ||
const digest = crypto | ||
.createHash('sha1') | ||
const digest = createHash('sha1') | ||
.update(key + GUID) | ||
@@ -284,3 +281,3 @@ .digest('base64'); | ||
const ws = new WebSocket(null); | ||
var protocol = req.headers['sec-websocket-protocol']; | ||
let protocol = req.headers['sec-websocket-protocol']; | ||
@@ -307,3 +304,3 @@ if (protocol) { | ||
const params = extensions[PerMessageDeflate.extensionName].params; | ||
const value = extension.format({ | ||
const value = format({ | ||
[PerMessageDeflate.extensionName]: [params] | ||
@@ -385,14 +382,12 @@ }); | ||
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) | ||
@@ -399,0 +394,0 @@ .map((h) => `${h}: ${headers[h]}`) |
'use strict'; | ||
const EventEmitter = require('events'); | ||
const crypto = require('crypto'); | ||
const https = require('https'); | ||
@@ -9,7 +8,6 @@ const http = require('http'); | ||
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'); | ||
@@ -25,2 +23,5 @@ const Sender = require('./sender'); | ||
} = require('./constants'); | ||
const { addEventListener, removeEventListener } = require('./event-target'); | ||
const { format, parse } = require('./extension'); | ||
const { toBuffer } = require('./buffer-util'); | ||
@@ -40,3 +41,3 @@ const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']; | ||
* | ||
* @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 | ||
@@ -63,2 +64,3 @@ * @param {Object} options Connection options | ||
if (address !== null) { | ||
this._bufferedAmount = 0; | ||
this._isServer = false; | ||
@@ -119,3 +121,3 @@ this._redirects = 0; | ||
get bufferedAmount() { | ||
if (!this._socket) return 0; | ||
if (!this._socket) return this._bufferedAmount; | ||
@@ -260,2 +262,6 @@ // | ||
ping(data, mask, cb) { | ||
if (this.readyState === WebSocket.CONNECTING) { | ||
throw new Error('WebSocket is not open: readyState 0 (CONNECTING)'); | ||
} | ||
if (typeof data === 'function') { | ||
@@ -269,13 +275,9 @@ cb = data; | ||
if (typeof data === 'number') data = data.toString(); | ||
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; | ||
sendAfterClose(this, data, cb); | ||
return; | ||
} | ||
if (typeof data === 'number') data = data.toString(); | ||
if (mask === undefined) mask = !this._isServer; | ||
@@ -294,2 +296,6 @@ this._sender.ping(data || EMPTY_BUFFER, mask, cb); | ||
pong(data, mask, cb) { | ||
if (this.readyState === WebSocket.CONNECTING) { | ||
throw new Error('WebSocket is not open: readyState 0 (CONNECTING)'); | ||
} | ||
if (typeof data === 'function') { | ||
@@ -303,13 +309,9 @@ cb = data; | ||
if (typeof data === 'number') data = data.toString(); | ||
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; | ||
sendAfterClose(this, data, cb); | ||
return; | ||
} | ||
if (typeof data === 'number') data = data.toString(); | ||
if (mask === undefined) mask = !this._isServer; | ||
@@ -324,3 +326,4 @@ this._sender.pong(data || EMPTY_BUFFER, mask, cb); | ||
* @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 | ||
@@ -333,2 +336,6 @@ * @param {Boolean} options.fin Specifies whether the fragment is the last one | ||
send(data, options, cb) { | ||
if (this.readyState === WebSocket.CONNECTING) { | ||
throw new Error('WebSocket is not open: readyState 0 (CONNECTING)'); | ||
} | ||
if (typeof options === 'function') { | ||
@@ -339,24 +346,17 @@ cb = options; | ||
if (typeof data === 'number') data = data.toString(); | ||
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; | ||
sendAfterClose(this, data, cb); | ||
return; | ||
} | ||
if (typeof data === 'number') data = data.toString(); | ||
const opts = { | ||
binary: typeof data !== 'string', | ||
mask: !this._isServer, | ||
compress: true, | ||
fin: true, | ||
...options | ||
}; | ||
const opts = Object.assign( | ||
{ | ||
binary: typeof data !== 'string', | ||
mask: !this._isServer, | ||
compress: true, | ||
fin: true | ||
}, | ||
options | ||
); | ||
if (!this._extensions[PerMessageDeflate.extensionName]) { | ||
@@ -406,3 +406,3 @@ opts.compress = false; | ||
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; | ||
@@ -421,3 +421,3 @@ } | ||
const listeners = this.listeners(method); | ||
for (var i = 0; i < listeners.length; i++) { | ||
for (let i = 0; i < listeners.length; i++) { | ||
// | ||
@@ -433,4 +433,4 @@ // Remove only the listeners added via `addEventListener`. | ||
WebSocket.prototype.addEventListener = EventTarget.addEventListener; | ||
WebSocket.prototype.removeEventListener = EventTarget.removeEventListener; | ||
WebSocket.prototype.addEventListener = addEventListener; | ||
WebSocket.prototype.removeEventListener = removeEventListener; | ||
@@ -443,3 +443,3 @@ module.exports = WebSocket; | ||
* @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 | ||
@@ -461,24 +461,20 @@ * @param {Object} options Connection options | ||
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, | ||
auth: undefined, | ||
host: undefined, | ||
path: undefined, | ||
port: undefined | ||
}; | ||
@@ -492,12 +488,9 @@ if (!protocolVersions.includes(opts.protocolVersion)) { | ||
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; | ||
@@ -515,8 +508,5 @@ } | ||
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; | ||
@@ -529,12 +519,10 @@ opts.createConnection = isSecure ? tlsConnect : netConnect; | ||
: 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; | ||
@@ -548,3 +536,3 @@ | ||
); | ||
opts.headers['Sec-WebSocket-Extensions'] = extension.format({ | ||
opts.headers['Sec-WebSocket-Extensions'] = format({ | ||
[PerMessageDeflate.extensionName]: perMessageDeflate.offer() | ||
@@ -563,5 +551,3 @@ }); | ||
} | ||
if (parsedUrl.auth) { | ||
opts.auth = parsedUrl.auth; | ||
} else if (parsedUrl.username || parsedUrl.password) { | ||
if (parsedUrl.username || parsedUrl.password) { | ||
opts.auth = `${parsedUrl.username}:${parsedUrl.password}`; | ||
@@ -571,3 +557,3 @@ } | ||
if (isUnixSocket) { | ||
const parts = path.split(':'); | ||
const parts = opts.path.split(':'); | ||
@@ -578,3 +564,3 @@ opts.socketPath = parts[0]; | ||
var req = (websocket._req = get(opts)); | ||
let req = (websocket._req = get(opts)); | ||
@@ -613,5 +599,3 @@ if (opts.timeout) { | ||
const addr = url.URL | ||
? new url.URL(location, address) | ||
: url.resolve(address, location); | ||
const addr = new URL(location, address); | ||
@@ -639,4 +623,3 @@ initAsClient(websocket, addr, protocols, options); | ||
const digest = crypto | ||
.createHash('sha1') | ||
const digest = createHash('sha1') | ||
.update(key + GUID) | ||
@@ -652,3 +635,3 @@ .digest('base64'); | ||
const protList = (protocols || '').split(/, */); | ||
var protError; | ||
let protError; | ||
@@ -672,5 +655,3 @@ if (!protocols && serverProt) { | ||
try { | ||
const extensions = extension.parse( | ||
res.headers['sec-websocket-extensions'] | ||
); | ||
const extensions = parse(res.headers['sec-websocket-extensions']); | ||
@@ -705,9 +686,3 @@ if (extensions[PerMessageDeflate.extensionName]) { | ||
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); | ||
@@ -756,2 +731,34 @@ } | ||
/** | ||
* 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. | ||
@@ -758,0 +765,0 @@ * |
{ | ||
"name": "ws", | ||
"version": "6.2.1", | ||
"version": "7.0.0", | ||
"description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js", | ||
@@ -28,19 +28,25 @@ "keywords": [ | ||
"integration": "npm run lint && mocha test/*.integration.js", | ||
"lint": "eslint --ignore-path .gitignore . && prettier --check --ignore-path .gitignore \"**/*.{json,md,yml}\"" | ||
"lint": "eslint --ignore-path .gitignore . && prettier --check --ignore-path .gitignore \"**/*.{json,md,yaml,yml}\"" | ||
}, | ||
"dependencies": { | ||
"async-limiter": "~1.0.0" | ||
"async-limiter": "^1.0.0" | ||
}, | ||
"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": "^5.16.0", | ||
"eslint-config-prettier": "^4.1.0", | ||
"eslint-plugin-prettier": "^3.0.1", | ||
"mocha": "^6.1.3", | ||
"nyc": "^14.0.0", | ||
"prettier": "^1.17.0", | ||
"utf-8-validate": "^5.0.2" | ||
}, | ||
"greenkeeper": { | ||
"commitMessages": { | ||
"dependencyUpdate": "[pkg] Update ${dependency} to version ${version}", | ||
"devDependencyUpdate": "[pkg] Update ${dependency} to version ${version}" | ||
} | ||
} | ||
} |
@@ -38,3 +38,2 @@ # ws: a Node.js WebSocket library | ||
- [Other examples](#other-examples) | ||
- [Error handling best practices](#error-handling-best-practices) | ||
- [FAQ](#faq) | ||
@@ -197,3 +196,3 @@ - [How to get the IP address of the client?](#how-to-get-the-ip-address-of-the-client) | ||
const server = new https.createServer({ | ||
const server = https.createServer({ | ||
cert: fs.readFileSync('/path/to/cert.pem'), | ||
@@ -314,26 +313,2 @@ key: fs.readFileSync('/path/to/key.pem') | ||
## 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 | ||
@@ -340,0 +315,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2831
101063
425
Updatedasync-limiter@^1.0.0