diff options
Diffstat (limited to 'middleware/node_modules/ws')
-rw-r--r-- | middleware/node_modules/ws/LICENSE | 19 | ||||
-rw-r--r-- | middleware/node_modules/ws/README.md | 489 | ||||
-rw-r--r-- | middleware/node_modules/ws/browser.js | 8 | ||||
-rw-r--r-- | middleware/node_modules/ws/index.js | 13 | ||||
-rw-r--r-- | middleware/node_modules/ws/package.json | 61 | ||||
-rw-r--r-- | middleware/node_modules/ws/wrapper.mjs | 8 |
6 files changed, 598 insertions, 0 deletions
diff --git a/middleware/node_modules/ws/LICENSE b/middleware/node_modules/ws/LICENSE new file mode 100644 index 0000000..65ff176 --- /dev/null +++ b/middleware/node_modules/ws/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/middleware/node_modules/ws/README.md b/middleware/node_modules/ws/README.md new file mode 100644 index 0000000..cab335b --- /dev/null +++ b/middleware/node_modules/ws/README.md @@ -0,0 +1,489 @@ +# ws: a Node.js WebSocket library + +[![Version npm](https://img.shields.io/npm/v/ws.svg?logo=npm)](https://www.npmjs.com/package/ws) +[![CI](https://img.shields.io/github/workflow/status/websockets/ws/CI/master?label=CI&logo=github)](https://github.com/websockets/ws/actions?query=workflow%3ACI+branch%3Amaster) +[![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg?logo=coveralls)](https://coveralls.io/github/websockets/ws) + +ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and +server implementation. + +Passes the quite extensive Autobahn test suite: [server][server-report], +[client][client-report]. + +**Note**: This module does not work in the browser. The client in the docs is a +reference to a back end with the role of a client in the WebSocket +communication. Browser clients must use the native +[`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) +object. To make the same code work seamlessly on Node.js and the browser, you +can use one of the many wrappers available on npm, like +[isomorphic-ws](https://github.com/heineiuo/isomorphic-ws). + +## Table of Contents + +- [Protocol support](#protocol-support) +- [Installing](#installing) + - [Opt-in for performance](#opt-in-for-performance) +- [API docs](#api-docs) +- [WebSocket compression](#websocket-compression) +- [Usage examples](#usage-examples) + - [Sending and receiving text data](#sending-and-receiving-text-data) + - [Sending binary data](#sending-binary-data) + - [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) + - [Round-trip time](#round-trip-time) + - [Use the Node.js streams API](#use-the-nodejs-streams-api) + - [Other examples](#other-examples) +- [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) + - [How to connect via a proxy?](#how-to-connect-via-a-proxy) +- [Changelog](#changelog) +- [License](#license) + +## Protocol support + +- **HyBi drafts 07-12** (Use the option `protocolVersion: 8`) +- **HyBi drafts 13-17** (Current default, alternatively option + `protocolVersion: 13`) + +## Installing + +``` +npm install ws +``` + +### Opt-in for performance + +There are 2 optional modules that can be installed along side with the ws +module. These modules are binary addons which improve certain operations. +Prebuilt binaries are available for the most popular platforms so you don't +necessarily need to have a C++ compiler installed on your machine. + +- `npm install --save-optional bufferutil`: Allows to efficiently perform + operations such as masking and unmasking the data payload of the WebSocket + frames. +- `npm install --save-optional utf-8-validate`: Allows to efficiently check if a + message contains valid UTF-8. + +## API docs + +See [`/doc/ws.md`](./doc/ws.md) for Node.js-like documentation of ws classes and +utility functions. + +## WebSocket compression + +ws supports the [permessage-deflate extension][permessage-deflate] which enables +the client and server to negotiate a compression algorithm and its parameters, +and then selectively apply it to the data payloads of each WebSocket message. + +The extension is disabled by default on the server and enabled by default on the +client. It adds a significant overhead in terms of performance and memory +consumption so we suggest to enable it only if it is really needed. + +Note that Node.js has a variety of issues with high-performance compression, +where increased concurrency, especially on Linux, can lead to [catastrophic +memory fragmentation][node-zlib-bug] and slow performance. If you intend to use +permessage-deflate in production, it is worthwhile to set up a test +representative of your workload and ensure Node.js/zlib will handle it with +acceptable performance and memory usage. + +Tuning of permessage-deflate can be done via the options defined below. You can +also use `zlibDeflateOptions` and `zlibInflateOptions`, which is passed directly +into the creation of [raw deflate/inflate streams][node-zlib-deflaterawdocs]. + +See [the docs][ws-server-options] for more options. + +```js +import WebSocket, { WebSocketServer } from 'ws'; + +const wss = new WebSocketServer({ + port: 8080, + perMessageDeflate: { + zlibDeflateOptions: { + // See zlib defaults. + chunkSize: 1024, + memLevel: 7, + level: 3 + }, + zlibInflateOptions: { + chunkSize: 10 * 1024 + }, + // Other options settable: + clientNoContextTakeover: true, // Defaults to negotiated value. + serverNoContextTakeover: true, // Defaults to negotiated value. + serverMaxWindowBits: 10, // Defaults to negotiated value. + // Below options specified as default values. + concurrencyLimit: 10, // Limits zlib concurrency for perf. + threshold: 1024 // Size (in bytes) below which messages + // should not be compressed if context takeover is disabled. + } +}); +``` + +The client will only use the extension if it is supported and enabled on the +server. To always disable the extension on the client set the +`perMessageDeflate` option to `false`. + +```js +import WebSocket from 'ws'; + +const ws = new WebSocket('ws://www.host.com/path', { + perMessageDeflate: false +}); +``` + +## Usage examples + +### Sending and receiving text data + +```js +import WebSocket from 'ws'; + +const ws = new WebSocket('ws://www.host.com/path'); + +ws.on('open', function open() { + ws.send('something'); +}); + +ws.on('message', function message(data) { + console.log('received: %s', data); +}); +``` + +### Sending binary data + +```js +import WebSocket from 'ws'; + +const ws = new WebSocket('ws://www.host.com/path'); + +ws.on('open', function open() { + const array = new Float32Array(5); + + for (var i = 0; i < array.length; ++i) { + array[i] = i / 2; + } + + ws.send(array); +}); +``` + +### Simple server + +```js +import { WebSocketServer } from 'ws'; + +const wss = new WebSocketServer({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.on('message', function message(data) { + console.log('received: %s', data); + }); + + ws.send('something'); +}); +``` + +### External HTTP/S server + +```js +import { createServer } from 'https'; +import { readFileSync } from 'fs'; +import { WebSocketServer } from 'ws'; + +const server = createServer({ + cert: readFileSync('/path/to/cert.pem'), + key: readFileSync('/path/to/key.pem') +}); +const wss = new WebSocketServer({ server }); + +wss.on('connection', function connection(ws) { + ws.on('message', function message(data) { + console.log('received: %s', data); + }); + + ws.send('something'); +}); + +server.listen(8080); +``` + +### Multiple servers sharing a single HTTP/S server + +```js +import { createServer } from 'http'; +import { parse } from 'url'; +import { WebSocketServer } from 'ws'; + +const server = createServer(); +const wss1 = new WebSocketServer({ noServer: true }); +const wss2 = new WebSocketServer({ noServer: true }); + +wss1.on('connection', function connection(ws) { + // ... +}); + +wss2.on('connection', function connection(ws) { + // ... +}); + +server.on('upgrade', function upgrade(request, socket, head) { + const { pathname } = parse(request.url); + + if (pathname === '/foo') { + wss1.handleUpgrade(request, socket, head, function done(ws) { + wss1.emit('connection', ws, request); + }); + } else if (pathname === '/bar') { + wss2.handleUpgrade(request, socket, head, function done(ws) { + wss2.emit('connection', ws, request); + }); + } else { + socket.destroy(); + } +}); + +server.listen(8080); +``` + +### Client authentication + +```js +import WebSocket from 'ws'; +import { createServer } from 'http'; + +const server = createServer(); +const wss = new WebSocketServer({ noServer: true }); + +wss.on('connection', function connection(ws, request, client) { + ws.on('message', function message(data) { + console.log(`Received message ${data} 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, function next(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 +import WebSocket, { WebSocketServer } from 'ws'; + +const wss = new WebSocketServer({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.on('message', function message(data, isBinary) { + wss.clients.forEach(function each(client) { + if (client.readyState === WebSocket.OPEN) { + client.send(data, { binary: isBinary }); + } + }); + }); +}); +``` + +A client WebSocket broadcasting to every other connected WebSocket clients, +excluding itself. + +```js +import WebSocket, { WebSocketServer } from 'ws'; + +const wss = new WebSocketServer({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.on('message', function message(data, isBinary) { + wss.clients.forEach(function each(client) { + if (client !== ws && client.readyState === WebSocket.OPEN) { + client.send(data, { binary: isBinary }); + } + }); + }); +}); +``` + +### Round-trip time + +```js +import WebSocket from 'ws'; + +const ws = new WebSocket('wss://websocket-echo.com/'); + +ws.on('open', function open() { + console.log('connected'); + ws.send(Date.now()); +}); + +ws.on('close', function close() { + console.log('disconnected'); +}); + +ws.on('message', function message(data) { + console.log(`Round-trip time: ${Date.now() - data} ms`); + + setTimeout(function timeout() { + ws.send(Date.now()); + }, 500); +}); +``` + +### Use the Node.js streams API + +```js +import WebSocket, { createWebSocketStream } from 'ws'; + +const ws = new WebSocket('wss://websocket-echo.com/'); + +const duplex = 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 +examples folder. + +Otherwise, see the test cases. + +## FAQ + +### How to get the IP address of the client? + +The remote IP address can be obtained from the raw socket. + +```js +import { WebSocketServer } from 'ws'; + +const wss = new WebSocketServer({ port: 8080 }); + +wss.on('connection', function connection(ws, req) { + const ip = req.socket.remoteAddress; +}); +``` + +When the server runs behind a proxy like NGINX, the de-facto standard is to use +the `X-Forwarded-For` header. + +```js +wss.on('connection', function connection(ws, req) { + const ip = req.headers['x-forwarded-for'].split(',')[0].trim(); +}); +``` + +### How to detect and close broken connections? + +Sometimes the link between the server and the client can be interrupted in a way +that keeps both the server and the client unaware of the broken state of the +connection (e.g. when pulling the cord). + +In these cases ping messages can be used as a means to verify that the remote +endpoint is still responsive. + +```js +import { WebSocketServer } from 'ws'; + +function heartbeat() { + this.isAlive = true; +} + +const wss = new WebSocketServer({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.isAlive = true; + ws.on('pong', heartbeat); +}); + +const interval = setInterval(function ping() { + wss.clients.forEach(function each(ws) { + if (ws.isAlive === false) return ws.terminate(); + + ws.isAlive = false; + ws.ping(); + }); +}, 30000); + +wss.on('close', function close() { + clearInterval(interval); +}); +``` + +Pong messages are automatically sent in response to ping messages as required by +the spec. + +Just like the server example above your clients might as well lose connection +without knowing it. You might want to add a ping listener on your clients to +prevent that. A simple implementation would be: + +```js +import WebSocket from 'ws'; + +function heartbeat() { + clearTimeout(this.pingTimeout); + + // 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); +} + +const client = new WebSocket('wss://websocket-echo.com/'); + +client.on('open', heartbeat); +client.on('ping', heartbeat); +client.on('close', function clear() { + clearTimeout(this.pingTimeout); +}); +``` + +### How to connect via a proxy? + +Use a custom `http.Agent` implementation like [https-proxy-agent][] or +[socks-proxy-agent][]. + +## Changelog + +We're using the GitHub [releases][changelog] for changelog entries. + +## License + +[MIT](LICENSE) + +[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 diff --git a/middleware/node_modules/ws/browser.js b/middleware/node_modules/ws/browser.js new file mode 100644 index 0000000..ca4f628 --- /dev/null +++ b/middleware/node_modules/ws/browser.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = function () { + throw new Error( + 'ws does not work in the browser. Browser clients must use the native ' + + 'WebSocket object' + ); +}; diff --git a/middleware/node_modules/ws/index.js b/middleware/node_modules/ws/index.js new file mode 100644 index 0000000..41edb3b --- /dev/null +++ b/middleware/node_modules/ws/index.js @@ -0,0 +1,13 @@ +'use strict'; + +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'); + +WebSocket.WebSocket = WebSocket; +WebSocket.WebSocketServer = WebSocket.Server; + +module.exports = WebSocket; diff --git a/middleware/node_modules/ws/package.json b/middleware/node_modules/ws/package.json new file mode 100644 index 0000000..57ddc7e --- /dev/null +++ b/middleware/node_modules/ws/package.json @@ -0,0 +1,61 @@ +{ + "name": "ws", + "version": "8.5.0", + "description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js", + "keywords": [ + "HyBi", + "Push", + "RFC-6455", + "WebSocket", + "WebSockets", + "real-time" + ], + "homepage": "https://github.com/websockets/ws", + "bugs": "https://github.com/websockets/ws/issues", + "repository": "websockets/ws", + "author": "Einar Otto Stangvik <einaros@gmail.com> (http://2x.io)", + "license": "MIT", + "main": "index.js", + "exports": { + "import": "./wrapper.mjs", + "require": "./index.js" + }, + "browser": "browser.js", + "engines": { + "node": ">=10.0.0" + }, + "files": [ + "browser.js", + "index.js", + "lib/*.js", + "wrapper.mjs" + ], + "scripts": { + "test": "nyc --reporter=lcov --reporter=text mocha --throw-deprecation test/*.test.js", + "integration": "mocha --throw-deprecation test/*.integration.js", + "lint": "eslint --ignore-path .gitignore . && prettier --check --ignore-path .gitignore \"**/*.{json,md,yaml,yml}\"" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + }, + "devDependencies": { + "benchmark": "^2.1.4", + "bufferutil": "^4.0.1", + "eslint": "^8.0.0", + "eslint-config-prettier": "^8.1.0", + "eslint-plugin-prettier": "^4.0.0", + "mocha": "^8.4.0", + "nyc": "^15.0.0", + "prettier": "^2.0.5", + "utf-8-validate": "^5.0.2" + } +} diff --git a/middleware/node_modules/ws/wrapper.mjs b/middleware/node_modules/ws/wrapper.mjs new file mode 100644 index 0000000..7245ad1 --- /dev/null +++ b/middleware/node_modules/ws/wrapper.mjs @@ -0,0 +1,8 @@ +import createWebSocketStream from './lib/stream.js'; +import Receiver from './lib/receiver.js'; +import Sender from './lib/sender.js'; +import WebSocket from './lib/websocket.js'; +import WebSocketServer from './lib/websocket-server.js'; + +export { createWebSocketStream, Receiver, Sender, WebSocket, WebSocketServer }; +export default WebSocket; |