mirror of
https://github.com/socketio/socket.io.git
synced 2026-04-30 03:00:39 -04:00
Compare commits
4 Commits
refactor/e
...
engine.io@
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
439a8f669c | ||
|
|
fc11285e14 | ||
|
|
b059af6b12 | ||
|
|
4e85378a46 |
@@ -296,7 +296,7 @@ A payload is a series of encoded packets tied together. The payload encoding for
|
||||
<length1>:<packet1>[<length2>:<packet2>[...]]
|
||||
```
|
||||
* length: length of the packet in __characters__
|
||||
* packet: actual packets as descriped above
|
||||
* packet: actual packets as described above
|
||||
|
||||
When XHR2 is not supported, the same encoding principle is used also when
|
||||
binary data is sent, but it is sent as base64 encoded strings. For the purposes of decoding, an identifier `b` is
|
||||
|
||||
@@ -48,6 +48,23 @@
|
||||
| [3.4.2](#342-2020-06-04) | June 2020 | `"` |
|
||||
| [3.4.1](#341-2020-04-17) | April 2020 | `^7.1.2` |
|
||||
|
||||
|
||||
## [6.6.7](https://github.com/socketio/socket.io/compare/engine.io@6.6.6...engine.io@6.6.7) (2026-04-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* close HTTP requests with invalid content type ([fc11285](https://github.com/socketio/socket.io/commit/fc11285e14964c2132d122164bf130c355f60671))
|
||||
* handle invalid packets when upgrading to WebTransport ([1fa1f46](https://github.com/socketio/socket.io/commit/1fa1f46cd420ac5b57bb4c04c959b58f3c79158c))
|
||||
* prevent WebTransport connections when a middleware is registered ([d1f5aa9](https://github.com/socketio/socket.io/commit/d1f5aa93722a7f1ed729b96f771daf92a3dfdaf7))
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
- [`ws@~8.18.3`](https://github.com/websockets/ws/releases/tag/8.18.3) (no change)
|
||||
|
||||
|
||||
|
||||
## [6.6.6](https://github.com/socketio/socket.io/compare/engine.io@6.6.5...engine.io@6.6.6) (2026-03-10)
|
||||
|
||||
|
||||
|
||||
@@ -764,18 +764,20 @@ export class Server extends BaseServer {
|
||||
/**
|
||||
* Handles an Engine.IO HTTP request.
|
||||
*
|
||||
* @param {EngineRequest} req
|
||||
* @param {IncomingMessage} req
|
||||
* @param {ServerResponse} res
|
||||
*/
|
||||
public handleRequest(req: EngineRequest, res: ServerResponse) {
|
||||
public handleRequest(req: IncomingMessage, res: ServerResponse) {
|
||||
debug('handling "%s" http request "%s"', req.method, req.url);
|
||||
this.prepare(req);
|
||||
req.res = res;
|
||||
const engineRequest = req as EngineRequest;
|
||||
|
||||
this.prepare(engineRequest);
|
||||
engineRequest.res = res;
|
||||
|
||||
const callback: ErrorCallback = (errorCode, errorContext) => {
|
||||
if (errorCode !== undefined) {
|
||||
this.emit("connection_error", {
|
||||
req,
|
||||
req: engineRequest,
|
||||
code: errorCode,
|
||||
message: Server.errorMessages[errorCode],
|
||||
context: errorContext,
|
||||
@@ -784,25 +786,27 @@ export class Server extends BaseServer {
|
||||
return;
|
||||
}
|
||||
|
||||
if (req._query.sid) {
|
||||
if (engineRequest._query.sid) {
|
||||
debug("setting new request for existing client");
|
||||
this.clients[req._query.sid].transport.onRequest(req);
|
||||
this.clients[engineRequest._query.sid].transport.onRequest(
|
||||
engineRequest,
|
||||
);
|
||||
} else {
|
||||
const closeConnection = (errorCode, errorContext) =>
|
||||
abortRequest(res, errorCode, errorContext);
|
||||
this.handshake(
|
||||
req._query.transport as TransportName,
|
||||
req,
|
||||
engineRequest._query.transport as TransportName,
|
||||
engineRequest,
|
||||
closeConnection,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
this._applyMiddlewares(req, res, (err) => {
|
||||
this._applyMiddlewares(engineRequest, res, (err) => {
|
||||
if (err) {
|
||||
callback(Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" });
|
||||
} else {
|
||||
this.verify(req, false, callback);
|
||||
this.verify(engineRequest, false, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -811,17 +815,19 @@ export class Server extends BaseServer {
|
||||
* Handles an Engine.IO HTTP Upgrade.
|
||||
*/
|
||||
public handleUpgrade(
|
||||
req: EngineRequest,
|
||||
req: IncomingMessage,
|
||||
socket: Duplex,
|
||||
upgradeHead: Buffer,
|
||||
) {
|
||||
this.prepare(req);
|
||||
const engineRequest = req as EngineRequest;
|
||||
|
||||
const res = new WebSocketResponse(req, socket);
|
||||
this.prepare(engineRequest);
|
||||
|
||||
const res = new WebSocketResponse(engineRequest, socket);
|
||||
const callback: ErrorCallback = (errorCode, errorContext) => {
|
||||
if (errorCode !== undefined) {
|
||||
this.emit("connection_error", {
|
||||
req,
|
||||
req: engineRequest,
|
||||
code: errorCode,
|
||||
message: Server.errorMessages[errorCode],
|
||||
context: errorContext,
|
||||
@@ -838,18 +844,22 @@ export class Server extends BaseServer {
|
||||
res.writeHead();
|
||||
|
||||
// delegate to ws
|
||||
this.ws.handleUpgrade(req, socket, head, (websocket) => {
|
||||
this.onWebSocket(req, socket, websocket);
|
||||
this.ws.handleUpgrade(engineRequest, socket, head, (websocket) => {
|
||||
this.onWebSocket(engineRequest, socket, websocket);
|
||||
});
|
||||
};
|
||||
|
||||
this._applyMiddlewares(req, res as unknown as ServerResponse, (err) => {
|
||||
if (err) {
|
||||
callback(Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" });
|
||||
} else {
|
||||
this.verify(req, true, callback);
|
||||
}
|
||||
});
|
||||
this._applyMiddlewares(
|
||||
engineRequest,
|
||||
res as unknown as ServerResponse,
|
||||
(err) => {
|
||||
if (err) {
|
||||
callback(Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" });
|
||||
} else {
|
||||
this.verify(engineRequest, true, callback);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -947,7 +957,7 @@ export class Server extends BaseServer {
|
||||
server.on("request", (req, res) => {
|
||||
if (check(req)) {
|
||||
debug('intercepting request for path "%s"', path);
|
||||
this.handleRequest(req as EngineRequest, res);
|
||||
this.handleRequest(req, res);
|
||||
} else {
|
||||
let i = 0;
|
||||
const l = listeners.length;
|
||||
@@ -960,7 +970,7 @@ export class Server extends BaseServer {
|
||||
if (~this.opts.transports.indexOf("websocket")) {
|
||||
server.on("upgrade", (req, socket, head) => {
|
||||
if (check(req)) {
|
||||
this.handleUpgrade(req as EngineRequest, socket, head);
|
||||
this.handleUpgrade(req, socket, head);
|
||||
} else if (false !== options.destroyUpgrade) {
|
||||
// default node behavior is to disconnect when no handlers
|
||||
// but by adding a handler, we prevent that
|
||||
|
||||
@@ -136,7 +136,8 @@ export class Polling extends Transport {
|
||||
const isBinary = "application/octet-stream" === req.headers["content-type"];
|
||||
|
||||
if (isBinary && this.protocol === 4) {
|
||||
return this.onError("invalid content");
|
||||
this.onError("invalid content");
|
||||
return res.writeStatus("400 Bad Request").end();
|
||||
}
|
||||
|
||||
this.dataReq = req;
|
||||
|
||||
@@ -122,7 +122,8 @@ export class Polling extends Transport {
|
||||
const isBinary = "application/octet-stream" === req.headers["content-type"];
|
||||
|
||||
if (isBinary && this.protocol === 4) {
|
||||
return this.onError("invalid content");
|
||||
this.onError("invalid content");
|
||||
return res.writeHead(400).end();
|
||||
}
|
||||
|
||||
this.dataReq = req;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "engine.io",
|
||||
"version": "6.6.6",
|
||||
"version": "6.6.7",
|
||||
"description": "The realtime engine behind Socket.IO. Provides the foundation of a bidirectional connection between client and server",
|
||||
"type": "commonjs",
|
||||
"main": "./build/engine.io.js",
|
||||
|
||||
@@ -60,6 +60,32 @@ exports.listen = (opts, fn) => {
|
||||
return e;
|
||||
};
|
||||
|
||||
exports.listenAsync = function listenAsync(opts = {}) {
|
||||
return new Promise((resolve) => {
|
||||
const engine = exports.listen(opts, (port) => {
|
||||
resolve({
|
||||
port,
|
||||
close: () => {
|
||||
engine.close();
|
||||
if (engine.httpServer) {
|
||||
engine.httpServer.close();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.runHandshake = async function runHandshake(port) {
|
||||
const res = await fetch(
|
||||
`http://localhost:${port}/engine.io/?EIO=4&transport=polling`,
|
||||
);
|
||||
const data = await res.text();
|
||||
return {
|
||||
sid: JSON.parse(data.substring(1)).sid,
|
||||
};
|
||||
};
|
||||
|
||||
exports.ClientSocket = Socket;
|
||||
|
||||
exports.createPartialDone = (done, count) => {
|
||||
|
||||
@@ -7,7 +7,13 @@ const path = require("path");
|
||||
const exec = require("child_process").exec;
|
||||
const zlib = require("zlib");
|
||||
const { Server, Socket, attach } = require("..");
|
||||
const { ClientSocket, listen, createPartialDone } = require("./common");
|
||||
const {
|
||||
ClientSocket,
|
||||
listen,
|
||||
listenAsync,
|
||||
runHandshake,
|
||||
createPartialDone,
|
||||
} = require("./common");
|
||||
const expect = require("expect.js");
|
||||
const request = require("superagent");
|
||||
const cookieMod = require("cookie");
|
||||
@@ -581,7 +587,7 @@ describe("server", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should not suggest upgrades when none are availble", (done) => {
|
||||
it("should not suggest upgrades when none are available", (done) => {
|
||||
listen({ transports: ["polling"] }, (port) => {
|
||||
const socket = new ClientSocket(`ws://localhost:${port}`, {});
|
||||
socket.on("handshake", (obj) => {
|
||||
@@ -1458,6 +1464,26 @@ describe("server", () => {
|
||||
},
|
||||
);
|
||||
|
||||
it("should abort the polling data request if the content type is invalid", async () => {
|
||||
const { port, close } = await listenAsync();
|
||||
const { sid } = await runHandshake(port);
|
||||
|
||||
const res = await fetch(
|
||||
`http://localhost:${port}/engine.io/?EIO=4&transport=polling&sid=${sid}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/octet-stream",
|
||||
},
|
||||
body: Buffer.of(1, 2, 3),
|
||||
},
|
||||
);
|
||||
|
||||
expect(res.status).to.eql(400);
|
||||
|
||||
close();
|
||||
});
|
||||
|
||||
// tests https://github.com/LearnBoost/engine.io-client/issues/207
|
||||
// websocket test, transport error
|
||||
it("should trigger transport close before open for ws", (done) => {
|
||||
|
||||
@@ -444,7 +444,7 @@ describe("server", () => {
|
||||
nio.emit<"noArgs">,
|
||||
);
|
||||
expectType<ToEmit<ServerToClientEventsNoAck, "helloFromServer">>(
|
||||
// These errors will dissapear once the TS version is updated from 4.7.4
|
||||
// These errors will disappear once the TS version is updated from 4.7.4
|
||||
// the TSD instance is using a newer version of TS than the workspace version
|
||||
// to enable the ability to compare against `any`
|
||||
sio.emit<"helloFromServer">,
|
||||
|
||||
Reference in New Issue
Block a user