Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: websockets/ws
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 8.5.0
Choose a base ref
...
head repository: websockets/ws
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8.6.0
Choose a head ref
  • 14 commits
  • 9 files changed
  • 3 contributors

Commits on Feb 25, 2022

  1. Copy the full SHA
    a0524e1 View commit details

Commits on Mar 5, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    7cf94db View commit details

Commits on Mar 6, 2022

  1. Copy the full SHA
    9c18b1e View commit details

Commits on Mar 10, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    dd3d5a7 View commit details

Commits on Mar 24, 2022

  1. [test] Do not use a relative URL

    Use different username and password in the redirect URL.
    lpinca committed Mar 24, 2022
    Copy the full SHA
    ff80d66 View commit details

Commits on Mar 26, 2022

  1. Copy the full SHA
    d086f4b View commit details

Commits on Apr 6, 2022

  1. [minor] Fix nit in comment

    lpinca committed Apr 6, 2022
    Copy the full SHA
    2619c00 View commit details

Commits on Apr 7, 2022

  1. [doc] Fix nits

    lpinca committed Apr 7, 2022
    Copy the full SHA
    62e9b19 View commit details

Commits on Apr 12, 2022

  1. Copy the full SHA
    2cf6202 View commit details

Commits on Apr 15, 2022

  1. [example] Fix require path

    lpinca committed Apr 15, 2022
    Copy the full SHA
    d062ded View commit details

Commits on Apr 22, 2022

  1. [ci] Do not test on node 17

    lpinca committed Apr 22, 2022
    Copy the full SHA
    0b6eb71 View commit details
  2. [ci] Test on node 18

    lpinca committed Apr 22, 2022
    Copy the full SHA
    69e6828 View commit details

Commits on Apr 24, 2022

  1. [feature] Introduce the 'redirect' event (#2030)

    Add the ability to remove confidential headers on a per-redirect basis.
    
    Closes #2014
    lpinca authored Apr 24, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8e3f118 View commit details

Commits on May 1, 2022

  1. [dist] 8.6.0

    lpinca committed May 1, 2022
    Copy the full SHA
    ba214d9 View commit details
Showing with 379 additions and 76 deletions.
  1. +3 −3 .github/workflows/ci.yml
  2. +1 −1 README.md
  3. +26 −7 doc/ws.md
  4. +2 −2 examples/express-session-parse/index.js
  5. +2 −2 examples/server-stats/index.js
  6. +2 −2 examples/ssl.js
  7. +36 −13 lib/websocket.js
  8. +1 −1 package.json
  9. +306 −45 test/websocket.test.js
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ jobs:
- 12
- 14
- 16
- 17
- 18
os:
- macOS-latest
- ubuntu-latest
@@ -28,8 +28,8 @@ jobs:
- arch: x86
os: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
architecture: ${{ matrix.arch }}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -252,8 +252,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 });
33 changes: 26 additions & 7 deletions doc/ws.md
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@
- [Event: 'open'](#event-open)
- [Event: 'ping'](#event-ping)
- [Event: 'pong'](#event-pong)
- [Event: 'redirect'](#event-redirect)
- [Event: 'unexpected-response'](#event-unexpected-response)
- [Event: 'upgrade'](#event-upgrade)
- [websocket.addEventListener(type, listener[, options])](#websocketaddeventlistenertype-listener-options)
@@ -72,7 +73,8 @@ This class represents a WebSocket server. It extends the `EventEmitter`.
- `handleProtocols` {Function} A function which can be used to handle the
WebSocket subprotocols. See description below.
- `host` {String} The hostname where to bind the server.
- `maxPayload` {Number} The maximum allowed message size in bytes.
- `maxPayload` {Number} The maximum allowed message size in bytes. Defaults to
100 MiB (104857600 bytes).
- `noServer` {Boolean} Enable no server mode.
- `path` {String} Accept only connections matching this path.
- `perMessageDeflate` {Boolean|Object} Enable/disable permessage-deflate.
@@ -279,7 +281,8 @@ This class represents a WebSocket. It extends the `EventEmitter`.
cryptographically strong random bytes.
- `handshakeTimeout` {Number} Timeout in milliseconds for the handshake
request. This is reset after every redirection.
- `maxPayload` {Number} The maximum allowed message size in bytes.
- `maxPayload` {Number} The maximum allowed message size in bytes. Defaults to
100 MiB (104857600 bytes).
- `maxRedirects` {Number} The maximum number of redirects allowed. Defaults
to 10.
- `origin` {String} Value of the `Origin` or `Sec-WebSocket-Origin` header
@@ -289,7 +292,7 @@ This class represents a WebSocket. It extends the `EventEmitter`.
- `skipUTF8Validation` {Boolean} Specifies whether or not to skip UTF-8
validation for text and close messages. Defaults to `false`. Set to `true`
only if the server is trusted.
- Any other option allowed in [http.request()][] or [https.request()][].
- Any other option allowed in [`http.request()`][] or [`https.request()`][].
Options given do not have any effect if parsed from the URL given with the
`address` parameter.

@@ -359,6 +362,19 @@ Emitted when a ping is received from the server.

Emitted when a pong is received from the server.

### Event: 'redirect'

- `url` {String}
- `request` {http.ClientRequest}

Emitted before a redirect is followed. `url` is the redirect URL. `request` is
the HTTP GET request with the headers queued. This event gives the ability to
inspect confidential headers and remove them on a per-redirect basis using the
[`request.getHeader()`][] and [`request.removeHeader()`][] API. The `request`
object should be used only for this purpose. When there is at least one listener
for this event, no header is removed by default, even if the redirect is to a
different domain.

### Event: 'unexpected-response'

- `request` {http.ClientRequest}
@@ -537,7 +553,7 @@ state is `CONNECTING`.

### websocket.terminate()

Forcibly close the connection. Internally this calls [socket.destroy()][].
Forcibly close the connection. Internally this calls [`socket.destroy()`][].

### websocket.url

@@ -608,11 +624,14 @@ as configured by the `maxPayload` option.
[concurrency-limit]: https://github.com/websockets/ws/issues/1202
[duplex-options]:
https://nodejs.org/api/stream.html#stream_new_stream_duplex_options
[http.request()]:
[`http.request()`]:
https://nodejs.org/api/http.html#http_http_request_options_callback
[https.request()]:
[`https.request()`]:
https://nodejs.org/api/https.html#https_https_request_options_callback
[permessage-deflate]:
https://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-19
[socket.destroy()]: https://nodejs.org/api/net.html#net_socket_destroy_error
[`request.getheader()`]: https://nodejs.org/api/http.html#requestgetheadername
[`request.removeheader()`]:
https://nodejs.org/api/http.html#requestremoveheadername
[`socket.destroy()`]: https://nodejs.org/api/net.html#net_socket_destroy_error
[zlib-options]: https://nodejs.org/api/zlib.html#zlib_class_options
4 changes: 2 additions & 2 deletions examples/express-session-parse/index.js
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ const express = require('express');
const http = require('http');
const uuid = require('uuid');

const WebSocket = require('../..');
const { WebSocketServer } = require('../..');

const app = express();
const map = new Map();
@@ -56,7 +56,7 @@ const server = http.createServer(app);
//
// Create a WebSocket server completely detached from the HTTP server.
//
const wss = new WebSocket.Server({ clientTracking: false, noServer: true });
const wss = new WebSocketServer({ clientTracking: false, noServer: true });

server.on('upgrade', function (request, socket, head) {
console.log('Parsing session from request...');
4 changes: 2 additions & 2 deletions examples/server-stats/index.js
Original file line number Diff line number Diff line change
@@ -4,13 +4,13 @@ const express = require('express');
const path = require('path');
const { createServer } = require('http');

const WebSocket = require('../../');
const { WebSocketServer } = require('../..');

const app = express();
app.use(express.static(path.join(__dirname, '/public')));

const server = createServer(app);
const wss = new WebSocket.Server({ server });
const wss = new WebSocketServer({ server });

wss.on('connection', function (ws) {
const id = setInterval(function () {
4 changes: 2 additions & 2 deletions examples/ssl.js
Original file line number Diff line number Diff line change
@@ -3,14 +3,14 @@
const https = require('https');
const fs = require('fs');

const WebSocket = require('..');
const { WebSocket, WebSocketServer } = require('..');

const server = https.createServer({
cert: fs.readFileSync('../test/fixtures/certificate.pem'),
key: fs.readFileSync('../test/fixtures/key.pem')
});

const wss = new WebSocket.Server({ server });
const wss = new WebSocketServer({ server });

wss.on('connection', function connection(ws) {
ws.on('message', function message(msg) {
49 changes: 36 additions & 13 deletions lib/websocket.js
Original file line number Diff line number Diff line change
@@ -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
@@ -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;

@@ -766,6 +767,8 @@ function initAsClient(websocket, address, protocols, options) {
opts.path = parts[1];
}

let req;

if (opts.followRedirects) {
if (websocket._redirects === 0) {
websocket._originalHost = parsedUrl.host;
@@ -783,7 +786,10 @@ function initAsClient(websocket, address, protocols, options) {
options.headers[key.toLowerCase()] = value;
}
}
} else if (parsedUrl.host !== websocket._originalHost) {
} else if (
websocket.listenerCount('redirect') === 0 &&
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.
@@ -803,9 +809,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 +835,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,8 +882,8 @@ 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;

@@ -947,10 +968,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 +1030,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 +1042,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'));
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ws",
"version": "8.5.0",
"version": "8.6.0",
"description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js",
"keywords": [
"HyBi",
351 changes: 306 additions & 45 deletions test/websocket.test.js

Large diffs are not rendered by default.