UNPKG

9.52 kBMarkdownView Raw
1# ws: a Node.js WebSocket library
2
3[![Version npm](https://img.shields.io/npm/v/ws.svg)](https://www.npmjs.com/package/ws)
4[![Linux Build](https://img.shields.io/travis/websockets/ws/master.svg)](https://travis-ci.org/websockets/ws)
5[![Windows Build](https://ci.appveyor.com/api/projects/status/github/websockets/ws?branch=master&svg=true)](https://ci.appveyor.com/project/lpinca/ws)
6[![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg)](https://coveralls.io/r/websockets/ws?branch=master)
7
8ws is a simple to use, blazing fast, and thoroughly tested WebSocket client
9and server implementation.
10
11Passes the quite extensive Autobahn test suite: [server][server-report],
12[client][client-report].
13
14**Note**: This module does not work in the browser. The client in the docs is a
15reference to a back end with the role of a client in the WebSocket
16communication. Browser clients must use the native
17[`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) object.
18
19## Table of Contents
20
21* [Protocol support](#protocol-support)
22* [Installing](#installing)
23 + [Opt-in for performance and spec compliance](#opt-in-for-performance-and-spec-compliance)
24* [API docs](#api-docs)
25* [WebSocket compression](#websocket-compression)
26* [Usage examples](#usage-examples)
27 + [Sending and receiving text data](#sending-and-receiving-text-data)
28 + [Sending binary data](#sending-binary-data)
29 + [Server example](#server-example)
30 + [Broadcast example](#broadcast-example)
31 + [ExpressJS example](#expressjs-example)
32 + [echo.websocket.org demo](#echowebsocketorg-demo)
33 + [Other examples](#other-examples)
34* [Error handling best practices](#error-handling-best-practices)
35* [FAQ](#faq)
36 + [How to get the IP address of the client?](#how-to-get-the-ip-address-of-the-client)
37 + [How to detect and close broken connections?](#how-to-detect-and-close-broken-connections)
38 + [How to connect via a proxy?](#how-to-connect-via-a-proxy)
39* [Changelog](#changelog)
40* [License](#license)
41
42## Protocol support
43
44* **HyBi drafts 07-12** (Use the option `protocolVersion: 8`)
45* **HyBi drafts 13-17** (Current default, alternatively option `protocolVersion: 13`)
46
47## Installing
48
49```
50npm install --save ws
51```
52
53### Opt-in for performance and spec compliance
54
55There are 2 optional modules that can be installed along side with the ws
56module. These modules are binary addons which improve certain operations.
57Prebuilt binaries are available for the most popular platforms so you don't
58necessarily need to have a C++ compiler installed on your machine.
59
60- `npm install --save-optional bufferutil`: Allows to efficiently perform
61 operations such as masking and unmasking the data payload of the WebSocket
62 frames.
63- `npm install --save-optional utf-8-validate`: Allows to efficiently check
64 if a message contains valid UTF-8 as required by the spec.
65
66## API docs
67
68See [`/doc/ws.md`](./doc/ws.md) for Node.js-like docs for the ws classes.
69
70## WebSocket compression
71
72ws supports the [permessage-deflate extension][permessage-deflate] which
73enables the client and server to negotiate a compression algorithm and its
74parameters, and then selectively apply it to the data payloads of each
75WebSocket message.
76
77The extension is disabled by default on the server and enabled by default on
78the client. It adds a significant overhead in terms of performance and memory
79consumption so we suggest to enable it only if it is really needed.
80
81The client will only use the extension if it is supported and enabled on the
82server. To always disable the extension on the client set the
83`perMessageDeflate` option to `false`.
84
85```js
86const WebSocket = require('ws');
87
88const ws = new WebSocket('ws://www.host.com/path', {
89 perMessageDeflate: false
90});
91```
92
93## Usage examples
94
95### Sending and receiving text data
96
97```js
98const WebSocket = require('ws');
99
100const ws = new WebSocket('ws://www.host.com/path');
101
102ws.on('open', function open() {
103 ws.send('something');
104});
105
106ws.on('message', function incoming(data) {
107 console.log(data);
108});
109```
110
111### Sending binary data
112
113```js
114const WebSocket = require('ws');
115
116const ws = new WebSocket('ws://www.host.com/path');
117
118ws.on('open', function open() {
119 const array = new Float32Array(5);
120
121 for (var i = 0; i < array.length; ++i) {
122 array[i] = i / 2;
123 }
124
125 ws.send(array);
126});
127```
128
129### Server example
130
131```js
132const WebSocket = require('ws');
133
134const wss = new WebSocket.Server({ port: 8080 });
135
136wss.on('connection', function connection(ws) {
137 ws.on('message', function incoming(message) {
138 console.log('received: %s', message);
139 });
140
141 ws.send('something');
142});
143```
144
145### Broadcast example
146
147```js
148const WebSocket = require('ws');
149
150const wss = new WebSocket.Server({ port: 8080 });
151
152// Broadcast to all.
153wss.broadcast = function broadcast(data) {
154 wss.clients.forEach(function each(client) {
155 if (client.readyState === WebSocket.OPEN) {
156 client.send(data);
157 }
158 });
159};
160
161wss.on('connection', function connection(ws) {
162 ws.on('message', function incoming(data) {
163 // Broadcast to everyone else.
164 wss.clients.forEach(function each(client) {
165 if (client !== ws && client.readyState === WebSocket.OPEN) {
166 client.send(data);
167 }
168 });
169 });
170});
171```
172
173### ExpressJS example
174
175```js
176const express = require('express');
177const http = require('http');
178const url = require('url');
179const WebSocket = require('ws');
180
181const app = express();
182
183app.use(function (req, res) {
184 res.send({ msg: "hello" });
185});
186
187const server = http.createServer(app);
188const wss = new WebSocket.Server({ server });
189
190wss.on('connection', function connection(ws, req) {
191 const location = url.parse(req.url, true);
192 // You might use location.query.access_token to authenticate or share sessions
193 // or req.headers.cookie (see http://stackoverflow.com/a/16395220/151312)
194
195 ws.on('message', function incoming(message) {
196 console.log('received: %s', message);
197 });
198
199 ws.send('something');
200});
201
202server.listen(8080, function listening() {
203 console.log('Listening on %d', server.address().port);
204});
205```
206
207### echo.websocket.org demo
208
209```js
210const WebSocket = require('ws');
211
212const ws = new WebSocket('wss://echo.websocket.org/', {
213 origin: 'https://websocket.org'
214});
215
216ws.on('open', function open() {
217 console.log('connected');
218 ws.send(Date.now());
219});
220
221ws.on('close', function close() {
222 console.log('disconnected');
223});
224
225ws.on('message', function incoming(data) {
226 console.log(`Roundtrip time: ${Date.now() - data} ms`);
227
228 setTimeout(function timeout() {
229 ws.send(Date.now());
230 }, 500);
231});
232```
233
234### Other examples
235
236For a full example with a browser client communicating with a ws server, see the
237examples folder.
238
239Otherwise, see the test cases.
240
241## Error handling best practices
242
243```js
244// If the WebSocket is closed before the following send is attempted
245ws.send('something');
246
247// Errors (both immediate and async write errors) can be detected in an optional
248// callback. The callback is also the only way of being notified that data has
249// actually been sent.
250ws.send('something', function ack(error) {
251 // If error is not defined, the send has been completed, otherwise the error
252 // object will indicate what failed.
253});
254
255// Immediate errors can also be handled with `try...catch`, but **note** that
256// since sends are inherently asynchronous, socket write failures will *not* be
257// captured when this technique is used.
258try { ws.send('something'); }
259catch (e) { /* handle error */ }
260```
261
262## FAQ
263
264### How to get the IP address of the client?
265
266The remote IP address can be obtained from the raw socket.
267
268```js
269const WebSocket = require('ws');
270
271const wss = new WebSocket.Server({ port: 8080 });
272
273wss.on('connection', function connection(ws, req) {
274 const ip = req.connection.remoteAddress;
275});
276```
277
278When the server runs behind a proxy like NGINX, the de-facto standard is to use
279the `X-Forwarded-For` header.
280
281```js
282wss.on('connection', function connection(ws, req) {
283 const ip = req.headers['x-forwarded-for'];
284});
285```
286
287### How to detect and close broken connections?
288
289Sometimes the link between the server and the client can be interrupted in a
290way that keeps both the server and the client unaware of the broken state of the
291connection (e.g. when pulling the cord).
292
293In these cases ping messages can be used as a means to verify that the remote
294endpoint is still responsive.
295
296```js
297const WebSocket = require('ws');
298
299const wss = new WebSocket.Server({ port: 8080 });
300
301function heartbeat() {
302 this.isAlive = true;
303}
304
305wss.on('connection', function connection(ws) {
306 ws.isAlive = true;
307 ws.on('pong', heartbeat);
308});
309
310const interval = setInterval(function ping() {
311 wss.clients.forEach(function each(ws) {
312 if (ws.isAlive === false) return ws.terminate();
313
314 ws.isAlive = false;
315 ws.ping('', false, true);
316 });
317}, 30000);
318```
319
320Pong messages are automatically sent in response to ping messages as required
321by the spec.
322
323### How to connect via a proxy?
324
325Use a custom `http.Agent` implementation like [https-proxy-agent][] or
326[socks-proxy-agent][].
327
328## Changelog
329
330We're using the GitHub [releases][changelog] for changelog entries.
331
332## License
333
334[MIT](LICENSE)
335
336[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent
337[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent
338[client-report]: http://websockets.github.io/ws/autobahn/clients/
339[server-report]: http://websockets.github.io/ws/autobahn/servers/
340[permessage-deflate]: https://tools.ietf.org/html/rfc7692
341[changelog]: https://github.com/websockets/ws/releases