source: frontend/node_modules/ws/README.md

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 13.5 KB
Line 
1# ws: a Node.js WebSocket library
2
3[![Version npm](https://img.shields.io/npm/v/ws.svg?logo=npm)](https://www.npmjs.com/package/ws)
4[![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)
5[![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg?logo=coveralls)](https://coveralls.io/github/websockets/ws)
6
7ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and
8server implementation.
9
10Passes the quite extensive Autobahn test suite: [server][server-report],
11[client][client-report].
12
13**Note**: This module does not work in the browser. The client in the docs is a
14reference to a back end with the role of a client in the WebSocket
15communication. Browser clients must use the native
16[`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
17object. To make the same code work seamlessly on Node.js and the browser, you
18can use one of the many wrappers available on npm, like
19[isomorphic-ws](https://github.com/heineiuo/isomorphic-ws).
20
21## Table of Contents
22
23- [Protocol support](#protocol-support)
24- [Installing](#installing)
25 - [Opt-in for performance](#opt-in-for-performance)
26- [API docs](#api-docs)
27- [WebSocket compression](#websocket-compression)
28- [Usage examples](#usage-examples)
29 - [Sending and receiving text data](#sending-and-receiving-text-data)
30 - [Sending binary data](#sending-binary-data)
31 - [Simple server](#simple-server)
32 - [External HTTP/S server](#external-https-server)
33 - [Multiple servers sharing a single HTTP/S server](#multiple-servers-sharing-a-single-https-server)
34 - [Client authentication](#client-authentication)
35 - [Server broadcast](#server-broadcast)
36 - [echo.websocket.org demo](#echowebsocketorg-demo)
37 - [Use the Node.js streams API](#use-the-nodejs-streams-api)
38 - [Other examples](#other-examples)
39- [FAQ](#faq)
40 - [How to get the IP address of the client?](#how-to-get-the-ip-address-of-the-client)
41 - [How to detect and close broken connections?](#how-to-detect-and-close-broken-connections)
42 - [How to connect via a proxy?](#how-to-connect-via-a-proxy)
43- [Changelog](#changelog)
44- [License](#license)
45
46## Protocol support
47
48- **HyBi drafts 07-12** (Use the option `protocolVersion: 8`)
49- **HyBi drafts 13-17** (Current default, alternatively option
50 `protocolVersion: 13`)
51
52## Installing
53
54```
55npm install ws
56```
57
58### Opt-in for performance
59
60There are 2 optional modules that can be installed along side with the ws
61module. These modules are binary addons which improve certain operations.
62Prebuilt binaries are available for the most popular platforms so you don't
63necessarily need to have a C++ compiler installed on your machine.
64
65- `npm install --save-optional bufferutil`: Allows to efficiently perform
66 operations such as masking and unmasking the data payload of the WebSocket
67 frames.
68- `npm install --save-optional utf-8-validate`: Allows to efficiently check if a
69 message contains valid UTF-8.
70
71## API docs
72
73See [`/doc/ws.md`](./doc/ws.md) for Node.js-like documentation of ws classes and
74utility functions.
75
76## WebSocket compression
77
78ws supports the [permessage-deflate extension][permessage-deflate] which enables
79the client and server to negotiate a compression algorithm and its parameters,
80and then selectively apply it to the data payloads of each WebSocket message.
81
82The extension is disabled by default on the server and enabled by default on the
83client. It adds a significant overhead in terms of performance and memory
84consumption so we suggest to enable it only if it is really needed.
85
86Note that Node.js has a variety of issues with high-performance compression,
87where increased concurrency, especially on Linux, can lead to [catastrophic
88memory fragmentation][node-zlib-bug] and slow performance. If you intend to use
89permessage-deflate in production, it is worthwhile to set up a test
90representative of your workload and ensure Node.js/zlib will handle it with
91acceptable performance and memory usage.
92
93Tuning of permessage-deflate can be done via the options defined below. You can
94also use `zlibDeflateOptions` and `zlibInflateOptions`, which is passed directly
95into the creation of [raw deflate/inflate streams][node-zlib-deflaterawdocs].
96
97See [the docs][ws-server-options] for more options.
98
99```js
100const WebSocket = require('ws');
101
102const wss = new WebSocket.Server({
103 port: 8080,
104 perMessageDeflate: {
105 zlibDeflateOptions: {
106 // See zlib defaults.
107 chunkSize: 1024,
108 memLevel: 7,
109 level: 3
110 },
111 zlibInflateOptions: {
112 chunkSize: 10 * 1024
113 },
114 // Other options settable:
115 clientNoContextTakeover: true, // Defaults to negotiated value.
116 serverNoContextTakeover: true, // Defaults to negotiated value.
117 serverMaxWindowBits: 10, // Defaults to negotiated value.
118 // Below options specified as default values.
119 concurrencyLimit: 10, // Limits zlib concurrency for perf.
120 threshold: 1024 // Size (in bytes) below which messages
121 // should not be compressed.
122 }
123});
124```
125
126The client will only use the extension if it is supported and enabled on the
127server. To always disable the extension on the client set the
128`perMessageDeflate` option to `false`.
129
130```js
131const WebSocket = require('ws');
132
133const ws = new WebSocket('ws://www.host.com/path', {
134 perMessageDeflate: false
135});
136```
137
138## Usage examples
139
140### Sending and receiving text data
141
142```js
143const WebSocket = require('ws');
144
145const ws = new WebSocket('ws://www.host.com/path');
146
147ws.on('open', function open() {
148 ws.send('something');
149});
150
151ws.on('message', function incoming(data) {
152 console.log(data);
153});
154```
155
156### Sending binary data
157
158```js
159const WebSocket = require('ws');
160
161const ws = new WebSocket('ws://www.host.com/path');
162
163ws.on('open', function open() {
164 const array = new Float32Array(5);
165
166 for (var i = 0; i < array.length; ++i) {
167 array[i] = i / 2;
168 }
169
170 ws.send(array);
171});
172```
173
174### Simple server
175
176```js
177const WebSocket = require('ws');
178
179const wss = new WebSocket.Server({ port: 8080 });
180
181wss.on('connection', function connection(ws) {
182 ws.on('message', function incoming(message) {
183 console.log('received: %s', message);
184 });
185
186 ws.send('something');
187});
188```
189
190### External HTTP/S server
191
192```js
193const fs = require('fs');
194const https = require('https');
195const WebSocket = require('ws');
196
197const server = https.createServer({
198 cert: fs.readFileSync('/path/to/cert.pem'),
199 key: fs.readFileSync('/path/to/key.pem')
200});
201const wss = new WebSocket.Server({ server });
202
203wss.on('connection', function connection(ws) {
204 ws.on('message', function incoming(message) {
205 console.log('received: %s', message);
206 });
207
208 ws.send('something');
209});
210
211server.listen(8080);
212```
213
214### Multiple servers sharing a single HTTP/S server
215
216```js
217const http = require('http');
218const WebSocket = require('ws');
219const url = require('url');
220
221const server = http.createServer();
222const wss1 = new WebSocket.Server({ noServer: true });
223const wss2 = new WebSocket.Server({ noServer: true });
224
225wss1.on('connection', function connection(ws) {
226 // ...
227});
228
229wss2.on('connection', function connection(ws) {
230 // ...
231});
232
233server.on('upgrade', function upgrade(request, socket, head) {
234 const pathname = url.parse(request.url).pathname;
235
236 if (pathname === '/foo') {
237 wss1.handleUpgrade(request, socket, head, function done(ws) {
238 wss1.emit('connection', ws, request);
239 });
240 } else if (pathname === '/bar') {
241 wss2.handleUpgrade(request, socket, head, function done(ws) {
242 wss2.emit('connection', ws, request);
243 });
244 } else {
245 socket.destroy();
246 }
247});
248
249server.listen(8080);
250```
251
252### Client authentication
253
254```js
255const http = require('http');
256const WebSocket = require('ws');
257
258const server = http.createServer();
259const wss = new WebSocket.Server({ noServer: true });
260
261wss.on('connection', function connection(ws, request, client) {
262 ws.on('message', function message(msg) {
263 console.log(`Received message ${msg} from user ${client}`);
264 });
265});
266
267server.on('upgrade', function upgrade(request, socket, head) {
268 // This function is not defined on purpose. Implement it with your own logic.
269 authenticate(request, (err, client) => {
270 if (err || !client) {
271 socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
272 socket.destroy();
273 return;
274 }
275
276 wss.handleUpgrade(request, socket, head, function done(ws) {
277 wss.emit('connection', ws, request, client);
278 });
279 });
280});
281
282server.listen(8080);
283```
284
285Also see the provided [example][session-parse-example] using `express-session`.
286
287### Server broadcast
288
289A client WebSocket broadcasting to all connected WebSocket clients, including
290itself.
291
292```js
293const WebSocket = require('ws');
294
295const wss = new WebSocket.Server({ port: 8080 });
296
297wss.on('connection', function connection(ws) {
298 ws.on('message', function incoming(data) {
299 wss.clients.forEach(function each(client) {
300 if (client.readyState === WebSocket.OPEN) {
301 client.send(data);
302 }
303 });
304 });
305});
306```
307
308A client WebSocket broadcasting to every other connected WebSocket clients,
309excluding itself.
310
311```js
312const WebSocket = require('ws');
313
314const wss = new WebSocket.Server({ port: 8080 });
315
316wss.on('connection', function connection(ws) {
317 ws.on('message', function incoming(data) {
318 wss.clients.forEach(function each(client) {
319 if (client !== ws && client.readyState === WebSocket.OPEN) {
320 client.send(data);
321 }
322 });
323 });
324});
325```
326
327### echo.websocket.org demo
328
329```js
330const WebSocket = require('ws');
331
332const ws = new WebSocket('wss://echo.websocket.org/', {
333 origin: 'https://websocket.org'
334});
335
336ws.on('open', function open() {
337 console.log('connected');
338 ws.send(Date.now());
339});
340
341ws.on('close', function close() {
342 console.log('disconnected');
343});
344
345ws.on('message', function incoming(data) {
346 console.log(`Roundtrip time: ${Date.now() - data} ms`);
347
348 setTimeout(function timeout() {
349 ws.send(Date.now());
350 }, 500);
351});
352```
353
354### Use the Node.js streams API
355
356```js
357const WebSocket = require('ws');
358
359const ws = new WebSocket('wss://echo.websocket.org/', {
360 origin: 'https://websocket.org'
361});
362
363const duplex = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' });
364
365duplex.pipe(process.stdout);
366process.stdin.pipe(duplex);
367```
368
369### Other examples
370
371For a full example with a browser client communicating with a ws server, see the
372examples folder.
373
374Otherwise, see the test cases.
375
376## FAQ
377
378### How to get the IP address of the client?
379
380The remote IP address can be obtained from the raw socket.
381
382```js
383const WebSocket = require('ws');
384
385const wss = new WebSocket.Server({ port: 8080 });
386
387wss.on('connection', function connection(ws, req) {
388 const ip = req.socket.remoteAddress;
389});
390```
391
392When the server runs behind a proxy like NGINX, the de-facto standard is to use
393the `X-Forwarded-For` header.
394
395```js
396wss.on('connection', function connection(ws, req) {
397 const ip = req.headers['x-forwarded-for'].split(',')[0].trim();
398});
399```
400
401### How to detect and close broken connections?
402
403Sometimes the link between the server and the client can be interrupted in a way
404that keeps both the server and the client unaware of the broken state of the
405connection (e.g. when pulling the cord).
406
407In these cases ping messages can be used as a means to verify that the remote
408endpoint is still responsive.
409
410```js
411const WebSocket = require('ws');
412
413function noop() {}
414
415function heartbeat() {
416 this.isAlive = true;
417}
418
419const wss = new WebSocket.Server({ port: 8080 });
420
421wss.on('connection', function connection(ws) {
422 ws.isAlive = true;
423 ws.on('pong', heartbeat);
424});
425
426const interval = setInterval(function ping() {
427 wss.clients.forEach(function each(ws) {
428 if (ws.isAlive === false) return ws.terminate();
429
430 ws.isAlive = false;
431 ws.ping(noop);
432 });
433}, 30000);
434
435wss.on('close', function close() {
436 clearInterval(interval);
437});
438```
439
440Pong messages are automatically sent in response to ping messages as required by
441the spec.
442
443Just like the server example above your clients might as well lose connection
444without knowing it. You might want to add a ping listener on your clients to
445prevent that. A simple implementation would be:
446
447```js
448const WebSocket = require('ws');
449
450function heartbeat() {
451 clearTimeout(this.pingTimeout);
452
453 // Use `WebSocket#terminate()`, which immediately destroys the connection,
454 // instead of `WebSocket#close()`, which waits for the close timer.
455 // Delay should be equal to the interval at which your server
456 // sends out pings plus a conservative assumption of the latency.
457 this.pingTimeout = setTimeout(() => {
458 this.terminate();
459 }, 30000 + 1000);
460}
461
462const client = new WebSocket('wss://echo.websocket.org/');
463
464client.on('open', heartbeat);
465client.on('ping', heartbeat);
466client.on('close', function clear() {
467 clearTimeout(this.pingTimeout);
468});
469```
470
471### How to connect via a proxy?
472
473Use a custom `http.Agent` implementation like [https-proxy-agent][] or
474[socks-proxy-agent][].
475
476## Changelog
477
478We're using the GitHub [releases][changelog] for changelog entries.
479
480## License
481
482[MIT](LICENSE)
483
484[changelog]: https://github.com/websockets/ws/releases
485[client-report]: http://websockets.github.io/ws/autobahn/clients/
486[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent
487[node-zlib-bug]: https://github.com/nodejs/node/issues/8871
488[node-zlib-deflaterawdocs]:
489 https://nodejs.org/api/zlib.html#zlib_zlib_createdeflateraw_options
490[permessage-deflate]: https://tools.ietf.org/html/rfc7692
491[server-report]: http://websockets.github.io/ws/autobahn/servers/
492[session-parse-example]: ./examples/express-session-parse
493[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent
494[ws-server-options]:
495 https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback
Note: See TracBrowser for help on using the repository browser.