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: socketio/engine.io
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 6.5.2
Choose a base ref
...
head repository: socketio/engine.io
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 6.5.5
Choose a head ref
  • 13 commits
  • 11 files changed
  • 4 contributors

Commits on Aug 17, 2023

  1. Verified

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

Commits on Oct 5, 2023

  1. fix(webtransport): properly handle abruptly closed connections

    Refreshing the page with a client connected with WebTransport would
    trigger the following exception:
    
    > node:internal/process/promises:288
    >            triggerUncaughtException(err, true /* fromPromise */);
    >            ^
    >
    > [UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "0".] {
    >   code: 'ERR_UNHANDLED_REJECTION'
    > }
    
    Related: #688
    darrachequesne committed Oct 5, 2023

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    darrachequesne Damien Arrachequesne
    Copy the full SHA
    ff1c861 View commit details
  2. refactor: add cache-control header in the polling response

    This header should not be needed since the client already includes a
    cache busting query parameter ("t"), but a misconfigured CDN could
    ignore the query parameters and cache the server response.
    
    Related: socketio/socket.io#4842
    darrachequesne committed Oct 5, 2023

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    darrachequesne Damien Arrachequesne
    Copy the full SHA
    9545b44 View commit details

Commits on Oct 6, 2023

  1. chore(release): 6.5.3

    darrachequesne committed Oct 6, 2023

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    darrachequesne Damien Arrachequesne
    Copy the full SHA
    2da559a View commit details

Commits on Nov 9, 2023

  1. refactor: remove useless reference

    A reference to the initial IncomingMessage object (the first HTTP
    request of the session) is kept in memory by default (`socket.request`),
    so its attached ServerResponse object (`req.res`) would not be
    garbage-collected. This will now be the case.
    
    Note: the IncomingMessage object is needed in two cases:
    
    - when working with the `express-session` middleware (`request.session`)
    - when fetching the certificate of the client with `request.socket.getPeerCertificate()`
    
    That's why removing it would be a breaking change.
    darrachequesne committed Nov 9, 2023

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    darrachequesne Damien Arrachequesne
    Copy the full SHA
    f27a6c3 View commit details
  2. refactor: remove useless references

    Those timers are only used during the upgrade, so there is no need to
    keep those references in memory.
    darrachequesne committed Nov 9, 2023

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    darrachequesne Damien Arrachequesne
    Copy the full SHA
    3b5e79e View commit details
  3. Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    darrachequesne Damien Arrachequesne
    Copy the full SHA
    43c1c1c View commit details
  4. Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    darrachequesne Damien Arrachequesne
    Copy the full SHA
    39937f8 View commit details
  5. Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    darrachequesne Damien Arrachequesne
    Copy the full SHA
    09acb17 View commit details
  6. chore(release): 6.5.4

    darrachequesne committed Nov 9, 2023

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    darrachequesne Damien Arrachequesne
    Copy the full SHA
    ff0fbfb View commit details

Commits on Feb 23, 2024

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    0efa04b View commit details

Commits on Jun 18, 2024

  1. chore(deps): bump ws from 8.11.0 to 8.17.1 (#702)

    Bumps [ws](https://github.com/websockets/ws) from 8.11.0 to 8.17.1.
    - [Release notes](https://github.com/websockets/ws/releases)
    - [Commits](websockets/ws@8.11.0...8.17.1)
    
    ---
    updated-dependencies:
    - dependency-name: ws
      dependency-type: direct:production
    ...
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored and darrachequesne committed Jun 18, 2024

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    darrachequesne Damien Arrachequesne
    Copy the full SHA
    adaa207 View commit details
  2. chore(release): 6.5.5

    darrachequesne committed Jun 18, 2024

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    darrachequesne Damien Arrachequesne
    Copy the full SHA
    0cb977a View commit details
Showing with 148 additions and 71 deletions.
  1. +1 −0 .github/workflows/ci.yml
  2. +48 −0 CHANGELOG.md
  3. +0 −11 lib/server.ts
  4. +19 −32 lib/socket.ts
  5. +11 −10 lib/transport.ts
  6. +4 −0 lib/transports-uws/polling.ts
  7. +4 −0 lib/transports/polling.ts
  8. +3 −1 lib/transports/webtransport.ts
  9. +38 −10 package-lock.json
  10. +3 −2 package.json
  11. +17 −5 test/server.js
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ jobs:
matrix:
node-version:
- 18
- 20

steps:
- name: Checkout repository
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# History

## 2024

- [6.5.5](#655-2024-06-18) (Jun 2024) (from the [6.5.x](https://github.com/socketio/engine.io-client/tree/6.5.x) branch)

## 2023

- [6.5.4](#654-2023-11-09) (Nov 2023)
- [6.5.3](#653-2023-10-06) (Oct 2023)
- [6.5.2](#652-2023-08-01) (Aug 2023)
- [6.5.1](#651-2023-06-27) (Jun 2023)
- [6.5.0](#650-2023-06-16) (Jun 2023)
@@ -50,6 +56,48 @@

# Release notes

## [6.5.5](https://github.com/socketio/engine.io/compare/6.5.4...6.5.5) (2024-06-18)

This release contains a bump of the `ws` dependency, which includes an important [security fix](https://github.com/websockets/ws/commit/e55e5106f10fcbaac37cfa89759e4cc0d073a52c).

Advisory: https://github.com/advisories/GHSA-3h5v-q93c-6h6q

### Bug Fixes

* **types:** make socket.request writable ([#697](https://github.com/socketio/engine.io/issues/697)) ([0efa04b](https://github.com/socketio/engine.io/commit/0efa04b5841816d18b0c6ebf7c5f592f8382978a))

### Dependencies

- [`ws@~8.17.1`](https://github.com/websockets/ws/releases/tag/8.17.1) ([diff](https://github.com/websockets/ws/compare/8.11.0...8.17.1))



## [6.5.4](https://github.com/socketio/engine.io/compare/6.5.3...6.5.4) (2023-11-09)

This release contains some minor changes which should improve the memory usage of the server, notably [this](https://github.com/socketio/engine.io/commit/f27a6c35017e4eb37546949f754e09933102837a).


### Dependencies

- [`ws@~8.11.0`](https://github.com/websockets/ws/releases/tag/8.11.0) (no change)



## [6.5.3](https://github.com/socketio/engine.io/compare/6.5.2...6.5.3) (2023-10-06)


### Bug Fixes

* improve compatibility with node16 module resolution ([#689](https://github.com/socketio/engine.io/issues/689)) ([c6bf8c0](https://github.com/socketio/engine.io/commit/c6bf8c0f571aad7a5917f43860c8c3d74a9b429b))
* **webtransport:** properly handle abruptly closed connections ([ff1c861](https://github.com/socketio/engine.io/commit/ff1c8615483bab25acc9cf04fb40339b0bd78812))


### Dependencies

- [`ws@~8.11.0`](https://github.com/websockets/ws/releases/tag/8.11.0) (no change)



## [6.5.2](https://github.com/socketio/engine.io/compare/6.5.1...6.5.2) (2023-08-01)


11 changes: 0 additions & 11 deletions lib/server.ts
Original file line number Diff line number Diff line change
@@ -464,12 +464,6 @@ export abstract class BaseServer extends EventEmitter {
} else if ("websocket" === transportName) {
transport.perMessageDeflate = this.opts.perMessageDeflate;
}

if (req._query && req._query.b64) {
transport.supportsBinary = false;
} else {
transport.supportsBinary = true;
}
} catch (e) {
debug('error handshaking to transport "%s"', transportName);
this.emit("connection_error", {
@@ -862,11 +856,6 @@ export class Server extends BaseServer {
websocket.removeListener("error", onUpgradeError);

const transport = this.createTransport(req._query.transport, req);
if (req._query && req._query.b64) {
transport.supportsBinary = false;
} else {
transport.supportsBinary = true;
}
transport.perMessageDeflate = this.opts.perMessageDeflate;
client.maybeUpgrade(transport);
}
51 changes: 19 additions & 32 deletions lib/socket.ts
Original file line number Diff line number Diff line change
@@ -12,24 +12,24 @@ export interface SendOptions {
compress?: boolean;
}

type ReadyState = "opening" | "open" | "closing" | "closed";

export class Socket extends EventEmitter {
public readonly protocol: number;
// TODO for the next major release: do not keep the reference to the first HTTP request, as it stays in memory
public readonly request: IncomingMessage;
public request: IncomingMessage;
public readonly remoteAddress: string;

public _readyState: string;
public _readyState: ReadyState = "opening";
public transport: Transport;

private server: Server;
private upgrading: boolean;
private upgraded: boolean;
private writeBuffer: Packet[];
private packetsFn: Array<() => void>;
private sentCallbackFn: any[];
private cleanupFn: any[];
private checkIntervalTimer;
private upgradeTimeoutTimer;
private upgrading = false;
private upgraded = false;
private writeBuffer: Packet[] = [];
private packetsFn: Array<() => void> = [];
private sentCallbackFn: any[] = [];
private cleanupFn: any[] = [];
private pingTimeoutTimer;
private pingIntervalTimer;

@@ -45,7 +45,7 @@ export class Socket extends EventEmitter {
return this._readyState;
}

set readyState(state) {
set readyState(state: ReadyState) {
debug("readyState updated from %s to %s", this._readyState, state);
this._readyState = state;
}
@@ -59,13 +59,6 @@ export class Socket extends EventEmitter {
super();
this.id = id;
this.server = server;
this.upgrading = false;
this.upgraded = false;
this.readyState = "opening";
this.writeBuffer = [];
this.packetsFn = [];
this.sentCallbackFn = [];
this.cleanupFn = [];
this.request = req;
this.protocol = protocol;

@@ -81,8 +74,6 @@ export class Socket extends EventEmitter {
// see https://github.com/fails-components/webtransport/issues/114
}

this.checkIntervalTimer = null;
this.upgradeTimeoutTimer = null;
this.pingTimeoutTimer = null;
this.pingIntervalTimer = null;

@@ -183,7 +174,7 @@ export class Socket extends EventEmitter {
/**
* Called upon transport error.
*
* @param {Error} error object
* @param {Error} err - error object
* @api private
*/
private onError(err) {
@@ -265,21 +256,23 @@ export class Socket extends EventEmitter {
this.upgrading = true;

// set transport upgrade timer
this.upgradeTimeoutTimer = setTimeout(() => {
const upgradeTimeoutTimer = setTimeout(() => {
debug("client did not complete upgrade - closing transport");
cleanup();
if ("open" === transport.readyState) {
transport.close();
}
}, this.server.opts.upgradeTimeout);

let checkIntervalTimer;

const onPacket = (packet) => {
if ("ping" === packet.type && "probe" === packet.data) {
debug("got probe ping packet, sending pong");
transport.send([{ type: "pong", data: "probe" }]);
this.emit("upgrading", transport);
clearInterval(this.checkIntervalTimer);
this.checkIntervalTimer = setInterval(check, 100);
clearInterval(checkIntervalTimer);
checkIntervalTimer = setInterval(check, 100);
} else if ("upgrade" === packet.type && this.readyState !== "closed") {
debug("got upgrade packet - upgrading");
cleanup();
@@ -311,11 +304,8 @@ export class Socket extends EventEmitter {
const cleanup = () => {
this.upgrading = false;

clearInterval(this.checkIntervalTimer);
this.checkIntervalTimer = null;

clearTimeout(this.upgradeTimeoutTimer);
this.upgradeTimeoutTimer = null;
clearInterval(checkIntervalTimer);
clearTimeout(upgradeTimeoutTimer);

transport.removeListener("packet", onPacket);
transport.removeListener("close", onTransportClose);
@@ -384,9 +374,6 @@ export class Socket extends EventEmitter {
clearTimeout(this.pingIntervalTimer);
clearTimeout(this.pingTimeoutTimer);

clearInterval(this.checkIntervalTimer);
this.checkIntervalTimer = null;
clearTimeout(this.upgradeTimeoutTimer);
// clean writeBuffer in next tick, so developers can still
// grab the writeBuffer on 'close' event
process.nextTick(() => {
21 changes: 11 additions & 10 deletions lib/transport.ts
Original file line number Diff line number Diff line change
@@ -15,13 +15,15 @@ const debug = debugModule("engine:transport");

function noop() {}

type ReadyState = "open" | "closing" | "closed";

export abstract class Transport extends EventEmitter {
public sid: string;
public writable: boolean;
public writable = false;
public protocol: number;

protected _readyState: string;
protected discarded: boolean;
protected _readyState: ReadyState = "open";
protected discarded = false;
protected parser: any;
protected req: IncomingMessage & { cleanup: Function };
protected supportsBinary: boolean;
@@ -30,7 +32,7 @@ export abstract class Transport extends EventEmitter {
return this._readyState;
}

set readyState(state) {
set readyState(state: ReadyState) {
debug(
"readyState updated from %s to %s (%s)",
this._readyState,
@@ -43,15 +45,14 @@ export abstract class Transport extends EventEmitter {
/**
* Transport constructor.
*
* @param {http.IncomingMessage} request
* @param {http.IncomingMessage} req
* @api public
*/
constructor(req) {
super();
this.readyState = "open";
this.discarded = false;
this.protocol = req._query.EIO === "4" ? 4 : 3; // 3rd revision by default
this.parser = this.protocol === 4 ? parser_v4 : parser_v3;
this.supportsBinary = !(req._query && req._query.b64);
}

/**
@@ -66,7 +67,7 @@ export abstract class Transport extends EventEmitter {
/**
* Called with an incoming HTTP request.
*
* @param {http.IncomingMessage} request
* @param {http.IncomingMessage} req
* @api protected
*/
protected onRequest(req) {
@@ -89,8 +90,8 @@ export abstract class Transport extends EventEmitter {
/**
* Called with a transport error.
*
* @param {String} message error
* @param {Object} error description
* @param {String} msg - message error
* @param {Object} desc - error description
* @api protected
*/
protected onError(msg: string, desc?) {
4 changes: 4 additions & 0 deletions lib/transports-uws/polling.ts
Original file line number Diff line number Diff line change
@@ -55,6 +55,8 @@ export class Polling extends Transport {
*/
onRequest(req) {
const res = req.res;
// remove the reference to the ServerResponse object (as the first request of the session is kept in memory by default)
req.res = null;

if (req.getMethod() === "get") {
this.onPollRequest(req, res);
@@ -423,6 +425,8 @@ export class Polling extends Transport {
headers["X-XSS-Protection"] = "0";
}

headers["cache-control"] = "no-store";

this.emit("headers", headers, req);
return headers;
}
4 changes: 4 additions & 0 deletions lib/transports/polling.ts
Original file line number Diff line number Diff line change
@@ -54,6 +54,8 @@ export class Polling extends Transport {
*/
onRequest(req: IncomingMessage & { res: ServerResponse }) {
const res = req.res;
// remove the reference to the ServerResponse object (as the first request of the session is kept in memory by default)
req.res = null;

if ("GET" === req.method) {
this.onPollRequest(req, res);
@@ -392,6 +394,8 @@ export class Polling extends Transport {
headers["X-XSS-Protection"] = "0";
}

headers["cache-control"] = "no-store";

this.emit("headers", headers, req);
return headers;
}
4 changes: 3 additions & 1 deletion lib/transports/webtransport.ts
Original file line number Diff line number Diff line change
@@ -14,7 +14,9 @@ export class WebTransport extends Transport {
super({ _query: { EIO: "4" } });

const transformStream = createPacketEncoderStream();
transformStream.readable.pipeTo(stream.writable);
transformStream.readable.pipeTo(stream.writable).catch(() => {
debug("the stream was closed");
});
this.writer = transformStream.writable.getWriter();

(async () => {
Loading