mirror of
https://github.com/ION606/archivebot.git
synced 2026-06-06 07:52:57 +00:00
Started adding slash commands, doesn't work though
This commit is contained in:
+9
-3
@@ -68,6 +68,13 @@ necessarily need to have a C++ compiler installed on your machine.
|
||||
- `npm install --save-optional utf-8-validate`: Allows to efficiently check if a
|
||||
message contains valid UTF-8.
|
||||
|
||||
To not even try to require and use these modules, use the
|
||||
[`WS_NO_BUFFER_UTIL`](./doc/ws.md#ws_no_buffer_util) and
|
||||
[`WS_NO_UTF_8_VALIDATE`](./doc/ws.md#ws_no_utf_8_validate) environment
|
||||
variables. These might be useful to enhance security in systems where a user can
|
||||
put a package in the package search path of an application of another user, due
|
||||
to how the Node.js resolver algorithm works.
|
||||
|
||||
## API docs
|
||||
|
||||
See [`/doc/ws.md`](./doc/ws.md) for Node.js-like documentation of ws classes and
|
||||
@@ -252,8 +259,8 @@ server.listen(8080);
|
||||
### Client authentication
|
||||
|
||||
```js
|
||||
import WebSocket from 'ws';
|
||||
import { createServer } from 'http';
|
||||
import { WebSocketServer } from 'ws';
|
||||
|
||||
const server = createServer();
|
||||
const wss = new WebSocketServer({ noServer: true });
|
||||
@@ -485,5 +492,4 @@ We're using the GitHub [releases][changelog] for changelog entries.
|
||||
[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
|
||||
[ws-server-options]: ./doc/ws.md#new-websocketserveroptions-callback
|
||||
|
||||
+20
-19
@@ -99,28 +99,29 @@ function toBuffer(data) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
try {
|
||||
const bufferUtil = require('bufferutil');
|
||||
module.exports = {
|
||||
concat,
|
||||
mask: _mask,
|
||||
toArrayBuffer,
|
||||
toBuffer,
|
||||
unmask: _unmask
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
concat,
|
||||
mask(source, mask, output, offset, length) {
|
||||
/* istanbul ignore else */
|
||||
if (!process.env.WS_NO_BUFFER_UTIL) {
|
||||
try {
|
||||
const bufferUtil = require('bufferutil');
|
||||
|
||||
module.exports.mask = function (source, mask, output, offset, length) {
|
||||
if (length < 48) _mask(source, mask, output, offset, length);
|
||||
else bufferUtil.mask(source, mask, output, offset, length);
|
||||
},
|
||||
toArrayBuffer,
|
||||
toBuffer,
|
||||
unmask(buffer, mask) {
|
||||
};
|
||||
|
||||
module.exports.unmask = function (buffer, mask) {
|
||||
if (buffer.length < 32) _unmask(buffer, mask);
|
||||
else bufferUtil.unmask(buffer, mask);
|
||||
}
|
||||
};
|
||||
} catch (e) /* istanbul ignore next */ {
|
||||
module.exports = {
|
||||
concat,
|
||||
mask: _mask,
|
||||
toArrayBuffer,
|
||||
toBuffer,
|
||||
unmask: _unmask
|
||||
};
|
||||
};
|
||||
} catch (e) {
|
||||
// Continue regardless of the error.
|
||||
}
|
||||
}
|
||||
|
||||
+15
-14
@@ -105,20 +105,21 @@ function _isValidUTF8(buf) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
const isValidUTF8 = require('utf-8-validate');
|
||||
module.exports = {
|
||||
isValidStatusCode,
|
||||
isValidUTF8: _isValidUTF8,
|
||||
tokenChars
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
isValidStatusCode,
|
||||
isValidUTF8(buf) {
|
||||
/* istanbul ignore else */
|
||||
if (!process.env.WS_NO_UTF_8_VALIDATE) {
|
||||
try {
|
||||
const isValidUTF8 = require('utf-8-validate');
|
||||
|
||||
module.exports.isValidUTF8 = function (buf) {
|
||||
return buf.length < 150 ? _isValidUTF8(buf) : isValidUTF8(buf);
|
||||
},
|
||||
tokenChars
|
||||
};
|
||||
} catch (e) /* istanbul ignore next */ {
|
||||
module.exports = {
|
||||
isValidStatusCode,
|
||||
isValidUTF8: _isValidUTF8,
|
||||
tokenChars
|
||||
};
|
||||
};
|
||||
} catch (e) {
|
||||
// Continue regardless of the error.
|
||||
}
|
||||
}
|
||||
|
||||
+82
-35
@@ -230,21 +230,36 @@ class WebSocketServer extends EventEmitter {
|
||||
handleUpgrade(req, socket, head, cb) {
|
||||
socket.on('error', socketOnError);
|
||||
|
||||
const key =
|
||||
req.headers['sec-websocket-key'] !== undefined
|
||||
? req.headers['sec-websocket-key']
|
||||
: false;
|
||||
const key = req.headers['sec-websocket-key'];
|
||||
const version = +req.headers['sec-websocket-version'];
|
||||
|
||||
if (
|
||||
req.method !== 'GET' ||
|
||||
req.headers.upgrade.toLowerCase() !== 'websocket' ||
|
||||
!key ||
|
||||
!keyRegex.test(key) ||
|
||||
(version !== 8 && version !== 13) ||
|
||||
!this.shouldHandle(req)
|
||||
) {
|
||||
return abortHandshake(socket, 400);
|
||||
if (req.method !== 'GET') {
|
||||
const message = 'Invalid HTTP method';
|
||||
abortHandshakeOrEmitwsClientError(this, req, socket, 405, message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.headers.upgrade.toLowerCase() !== 'websocket') {
|
||||
const message = 'Invalid Upgrade header';
|
||||
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!key || !keyRegex.test(key)) {
|
||||
const message = 'Missing or invalid Sec-WebSocket-Key header';
|
||||
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (version !== 8 && version !== 13) {
|
||||
const message = 'Missing or invalid Sec-WebSocket-Version header';
|
||||
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.shouldHandle(req)) {
|
||||
abortHandshake(socket, 400);
|
||||
return;
|
||||
}
|
||||
|
||||
const secWebSocketProtocol = req.headers['sec-websocket-protocol'];
|
||||
@@ -254,7 +269,9 @@ class WebSocketServer extends EventEmitter {
|
||||
try {
|
||||
protocols = subprotocol.parse(secWebSocketProtocol);
|
||||
} catch (err) {
|
||||
return abortHandshake(socket, 400);
|
||||
const message = 'Invalid Sec-WebSocket-Protocol header';
|
||||
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +296,10 @@ class WebSocketServer extends EventEmitter {
|
||||
extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
|
||||
}
|
||||
} catch (err) {
|
||||
return abortHandshake(socket, 400);
|
||||
const message =
|
||||
'Invalid or unacceptable Sec-WebSocket-Extensions header';
|
||||
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,7 +466,7 @@ function emitClose(server) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle premature socket errors.
|
||||
* Handle socket errors.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
@@ -464,25 +484,52 @@ function socketOnError() {
|
||||
* @private
|
||||
*/
|
||||
function abortHandshake(socket, code, message, headers) {
|
||||
if (socket.writable) {
|
||||
message = message || http.STATUS_CODES[code];
|
||||
headers = {
|
||||
Connection: 'close',
|
||||
'Content-Type': 'text/html',
|
||||
'Content-Length': Buffer.byteLength(message),
|
||||
...headers
|
||||
};
|
||||
//
|
||||
// The socket is writable unless the user destroyed or ended it before calling
|
||||
// `server.handleUpgrade()` or in the `verifyClient` function, which is a user
|
||||
// error. Handling this does not make much sense as the worst that can happen
|
||||
// is that some of the data written by the user might be discarded due to the
|
||||
// call to `socket.end()` below, which triggers an `'error'` event that in
|
||||
// turn causes the socket to be destroyed.
|
||||
//
|
||||
message = message || http.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` +
|
||||
Object.keys(headers)
|
||||
.map((h) => `${h}: ${headers[h]}`)
|
||||
.join('\r\n') +
|
||||
'\r\n\r\n' +
|
||||
message
|
||||
);
|
||||
}
|
||||
socket.once('finish', socket.destroy);
|
||||
|
||||
socket.removeListener('error', socketOnError);
|
||||
socket.destroy();
|
||||
socket.end(
|
||||
`HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` +
|
||||
Object.keys(headers)
|
||||
.map((h) => `${h}: ${headers[h]}`)
|
||||
.join('\r\n') +
|
||||
'\r\n\r\n' +
|
||||
message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a `'wsClientError'` event on a `WebSocketServer` if there is at least
|
||||
* one listener for it, otherwise call `abortHandshake()`.
|
||||
*
|
||||
* @param {WebSocketServer} server The WebSocket server
|
||||
* @param {http.IncomingMessage} req The request object
|
||||
* @param {(net.Socket|tls.Socket)} socket The socket of the upgrade request
|
||||
* @param {Number} code The HTTP response status code
|
||||
* @param {String} message The HTTP response body
|
||||
* @private
|
||||
*/
|
||||
function abortHandshakeOrEmitwsClientError(server, req, socket, code, message) {
|
||||
if (server.listenerCount('wsClientError')) {
|
||||
const err = new Error(message);
|
||||
Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);
|
||||
|
||||
server.emit('wsClientError', err, socket, req);
|
||||
} else {
|
||||
abortHandshake(socket, code, message);
|
||||
}
|
||||
}
|
||||
|
||||
+75
-34
@@ -30,10 +30,11 @@ const {
|
||||
const { format, parse } = require('./extension');
|
||||
const { toBuffer } = require('./buffer-util');
|
||||
|
||||
const closeTimeout = 30 * 1000;
|
||||
const kAborted = Symbol('kAborted');
|
||||
const protocolVersions = [8, 13];
|
||||
const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
|
||||
const subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
|
||||
const protocolVersions = [8, 13];
|
||||
const closeTimeout = 30 * 1000;
|
||||
|
||||
/**
|
||||
* Class representing a WebSocket.
|
||||
@@ -647,7 +648,7 @@ function initAsClient(websocket, address, protocols, options) {
|
||||
hostname: undefined,
|
||||
protocol: undefined,
|
||||
timeout: undefined,
|
||||
method: undefined,
|
||||
method: 'GET',
|
||||
host: undefined,
|
||||
path: undefined,
|
||||
port: undefined
|
||||
@@ -676,20 +677,20 @@ function initAsClient(websocket, address, protocols, options) {
|
||||
}
|
||||
|
||||
const isSecure = parsedUrl.protocol === 'wss:';
|
||||
const isUnixSocket = parsedUrl.protocol === 'ws+unix:';
|
||||
let invalidURLMessage;
|
||||
const isIpcUrl = parsedUrl.protocol === 'ws+unix:';
|
||||
let invalidUrlMessage;
|
||||
|
||||
if (parsedUrl.protocol !== 'ws:' && !isSecure && !isUnixSocket) {
|
||||
invalidURLMessage =
|
||||
if (parsedUrl.protocol !== 'ws:' && !isSecure && !isIpcUrl) {
|
||||
invalidUrlMessage =
|
||||
'The URL\'s protocol must be one of "ws:", "wss:", or "ws+unix:"';
|
||||
} else if (isUnixSocket && !parsedUrl.pathname) {
|
||||
invalidURLMessage = "The URL's pathname is empty";
|
||||
} else if (isIpcUrl && !parsedUrl.pathname) {
|
||||
invalidUrlMessage = "The URL's pathname is empty";
|
||||
} else if (parsedUrl.hash) {
|
||||
invalidURLMessage = 'The URL contains a fragment identifier';
|
||||
invalidUrlMessage = 'The URL contains a fragment identifier';
|
||||
}
|
||||
|
||||
if (invalidURLMessage) {
|
||||
const err = new SyntaxError(invalidURLMessage);
|
||||
if (invalidUrlMessage) {
|
||||
const err = new SyntaxError(invalidUrlMessage);
|
||||
|
||||
if (websocket._redirects === 0) {
|
||||
throw err;
|
||||
@@ -701,7 +702,7 @@ function initAsClient(websocket, address, protocols, options) {
|
||||
|
||||
const defaultPort = isSecure ? 443 : 80;
|
||||
const key = randomBytes(16).toString('base64');
|
||||
const get = isSecure ? https.get : http.get;
|
||||
const request = isSecure ? https.request : http.request;
|
||||
const protocolSet = new Set();
|
||||
let perMessageDeflate;
|
||||
|
||||
@@ -712,11 +713,11 @@ function initAsClient(websocket, address, protocols, options) {
|
||||
? parsedUrl.hostname.slice(1, -1)
|
||||
: parsedUrl.hostname;
|
||||
opts.headers = {
|
||||
...opts.headers,
|
||||
'Sec-WebSocket-Version': opts.protocolVersion,
|
||||
'Sec-WebSocket-Key': key,
|
||||
Connection: 'Upgrade',
|
||||
Upgrade: 'websocket',
|
||||
...opts.headers
|
||||
Upgrade: 'websocket'
|
||||
};
|
||||
opts.path = parsedUrl.pathname + parsedUrl.search;
|
||||
opts.timeout = opts.handshakeTimeout;
|
||||
@@ -759,16 +760,22 @@ function initAsClient(websocket, address, protocols, options) {
|
||||
opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
|
||||
}
|
||||
|
||||
if (isUnixSocket) {
|
||||
if (isIpcUrl) {
|
||||
const parts = opts.path.split(':');
|
||||
|
||||
opts.socketPath = parts[0];
|
||||
opts.path = parts[1];
|
||||
}
|
||||
|
||||
let req;
|
||||
|
||||
if (opts.followRedirects) {
|
||||
if (websocket._redirects === 0) {
|
||||
websocket._originalHost = parsedUrl.host;
|
||||
websocket._originalIpc = isIpcUrl;
|
||||
websocket._originalSecure = isSecure;
|
||||
websocket._originalHostOrSocketPath = isIpcUrl
|
||||
? opts.socketPath
|
||||
: parsedUrl.host;
|
||||
|
||||
const headers = options && options.headers;
|
||||
|
||||
@@ -783,15 +790,27 @@ function initAsClient(websocket, address, protocols, options) {
|
||||
options.headers[key.toLowerCase()] = value;
|
||||
}
|
||||
}
|
||||
} else if (parsedUrl.host !== websocket._originalHost) {
|
||||
//
|
||||
// Match curl 7.77.0 behavior and drop the following headers. These
|
||||
// headers are also dropped when following a redirect to a subdomain.
|
||||
//
|
||||
delete opts.headers.authorization;
|
||||
delete opts.headers.cookie;
|
||||
delete opts.headers.host;
|
||||
opts.auth = undefined;
|
||||
} else if (websocket.listenerCount('redirect') === 0) {
|
||||
const isSameHost = isIpcUrl
|
||||
? websocket._originalIpc
|
||||
? opts.socketPath === websocket._originalHostOrSocketPath
|
||||
: false
|
||||
: websocket._originalIpc
|
||||
? false
|
||||
: parsedUrl.host === websocket._originalHostOrSocketPath;
|
||||
|
||||
if (!isSameHost || (websocket._originalSecure && !isSecure)) {
|
||||
//
|
||||
// Match curl 7.77.0 behavior and drop the following headers. These
|
||||
// headers are also dropped when following a redirect to a subdomain.
|
||||
//
|
||||
delete opts.headers.authorization;
|
||||
delete opts.headers.cookie;
|
||||
|
||||
if (!isSameHost) delete opts.headers.host;
|
||||
|
||||
opts.auth = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -803,9 +822,24 @@ function initAsClient(websocket, address, protocols, options) {
|
||||
options.headers.authorization =
|
||||
'Basic ' + Buffer.from(opts.auth).toString('base64');
|
||||
}
|
||||
}
|
||||
|
||||
let req = (websocket._req = get(opts));
|
||||
req = websocket._req = request(opts);
|
||||
|
||||
if (websocket._redirects) {
|
||||
//
|
||||
// Unlike what is done for the `'upgrade'` event, no early exit is
|
||||
// triggered here if the user calls `websocket.close()` or
|
||||
// `websocket.terminate()` from a listener of the `'redirect'` event. This
|
||||
// is because the user can also call `request.destroy()` with an error
|
||||
// before calling `websocket.close()` or `websocket.terminate()` and this
|
||||
// would result in an error being emitted on the `request` object with no
|
||||
// `'error'` event listeners attached.
|
||||
//
|
||||
websocket.emit('redirect', websocket.url, req);
|
||||
}
|
||||
} else {
|
||||
req = websocket._req = request(opts);
|
||||
}
|
||||
|
||||
if (opts.timeout) {
|
||||
req.on('timeout', () => {
|
||||
@@ -814,7 +848,7 @@ function initAsClient(websocket, address, protocols, options) {
|
||||
}
|
||||
|
||||
req.on('error', (err) => {
|
||||
if (req === null || req.aborted) return;
|
||||
if (req === null || req[kAborted]) return;
|
||||
|
||||
req = websocket._req = null;
|
||||
emitErrorAndClose(websocket, err);
|
||||
@@ -861,13 +895,18 @@ function initAsClient(websocket, address, protocols, options) {
|
||||
websocket.emit('upgrade', res);
|
||||
|
||||
//
|
||||
// The user may have closed the connection from a listener of the `upgrade`
|
||||
// event.
|
||||
// The user may have closed the connection from a listener of the
|
||||
// `'upgrade'` event.
|
||||
//
|
||||
if (websocket.readyState !== WebSocket.CONNECTING) return;
|
||||
|
||||
req = websocket._req = null;
|
||||
|
||||
if (res.headers.upgrade.toLowerCase() !== 'websocket') {
|
||||
abortHandshake(websocket, socket, 'Invalid Upgrade header');
|
||||
return;
|
||||
}
|
||||
|
||||
const digest = createHash('sha1')
|
||||
.update(key + GUID)
|
||||
.digest('base64');
|
||||
@@ -947,10 +986,12 @@ function initAsClient(websocket, address, protocols, options) {
|
||||
skipUTF8Validation: opts.skipUTF8Validation
|
||||
});
|
||||
});
|
||||
|
||||
req.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit the `'error'` and `'close'` event.
|
||||
* Emit the `'error'` and `'close'` events.
|
||||
*
|
||||
* @param {WebSocket} websocket The WebSocket instance
|
||||
* @param {Error} The error to emit
|
||||
@@ -1007,6 +1048,7 @@ function abortHandshake(websocket, stream, message) {
|
||||
Error.captureStackTrace(err, abortHandshake);
|
||||
|
||||
if (stream.setHeader) {
|
||||
stream[kAborted] = true;
|
||||
stream.abort();
|
||||
|
||||
if (stream.socket && !stream.socket.destroyed) {
|
||||
@@ -1018,8 +1060,7 @@ function abortHandshake(websocket, stream, message) {
|
||||
stream.socket.destroy();
|
||||
}
|
||||
|
||||
stream.once('abort', websocket.emitClose.bind(websocket));
|
||||
websocket.emit('error', err);
|
||||
process.nextTick(emitErrorAndClose, websocket, err);
|
||||
} else {
|
||||
stream.destroy(err);
|
||||
stream.once('error', websocket.emit.bind(websocket, 'error'));
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ws",
|
||||
"version": "8.5.0",
|
||||
"version": "8.9.0",
|
||||
"description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js",
|
||||
"keywords": [
|
||||
"HyBi",
|
||||
|
||||
Reference in New Issue
Block a user