mirror of
https://github.com/socketio/socket.io.git
synced 2026-01-11 16:08:24 -05:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00d8ee5b05 | ||
|
|
2dd5fa9dd4 | ||
|
|
a5dff0ac83 | ||
|
|
3035c25982 | ||
|
|
63f181cc12 | ||
|
|
a250e283da | ||
|
|
e5c62cad60 | ||
|
|
01d37624a8 |
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -16,7 +16,9 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12, 14, 16]
|
||||
node-version:
|
||||
- 16
|
||||
- 20
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
|
||||
91
CHANGELOG.md
91
CHANGELOG.md
@@ -2,6 +2,7 @@
|
||||
|
||||
## 2023
|
||||
|
||||
- [4.7.0](#470-2023-06-22) (Jun 2023)
|
||||
- [4.6.2](#462-2023-05-31) (May 2023)
|
||||
- [4.6.1](#461-2023-02-20) (Feb 2023)
|
||||
- [4.6.0](#460-2023-02-07) (Feb 2023)
|
||||
@@ -58,6 +59,92 @@
|
||||
|
||||
# Release notes
|
||||
|
||||
## [4.7.0](https://github.com/socketio/socket.io/compare/4.6.2...4.7.0) (2023-06-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* remove the Partial modifier from the socket.data type ([#4740](https://github.com/socketio/socket.io/issues/4740)) ([e5c62ca](https://github.com/socketio/socket.io/commit/e5c62cad60fc7d16fbb024fd9be1d1880f4e6f5f))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
#### Support for WebTransport
|
||||
|
||||
The Engine.IO server can now use WebTransport as the underlying transport.
|
||||
|
||||
WebTransport is a web API that uses the HTTP/3 protocol as a bidirectional transport. It's intended for two-way communications between a web client and an HTTP/3 server.
|
||||
|
||||
References:
|
||||
|
||||
- https://w3c.github.io/webtransport/
|
||||
- https://developer.mozilla.org/en-US/docs/Web/API/WebTransport
|
||||
- https://developer.chrome.com/articles/webtransport/
|
||||
|
||||
Until WebTransport support lands [in Node.js](https://github.com/nodejs/node/issues/38478), you can use the `@fails-components/webtransport` package:
|
||||
|
||||
```js
|
||||
import { readFileSync } from "fs";
|
||||
import { createServer } from "https";
|
||||
import { Server } from "socket.io";
|
||||
import { Http3Server } from "@fails-components/webtransport";
|
||||
|
||||
// WARNING: the total length of the validity period MUST NOT exceed two weeks (https://w3c.github.io/webtransport/#custom-certificate-requirements)
|
||||
const cert = readFileSync("/path/to/my/cert.pem");
|
||||
const key = readFileSync("/path/to/my/key.pem");
|
||||
|
||||
const httpsServer = createServer({
|
||||
key,
|
||||
cert
|
||||
});
|
||||
|
||||
httpsServer.listen(3000);
|
||||
|
||||
const io = new Server(httpsServer, {
|
||||
transports: ["polling", "websocket", "webtransport"] // WebTransport is not enabled by default
|
||||
});
|
||||
|
||||
const h3Server = new Http3Server({
|
||||
port: 3000,
|
||||
host: "0.0.0.0",
|
||||
secret: "changeit",
|
||||
cert,
|
||||
privKey: key,
|
||||
});
|
||||
|
||||
(async () => {
|
||||
const stream = await h3Server.sessionStream("/engine.io/");
|
||||
const sessionReader = stream.getReader();
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await sessionReader.read();
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
io.engine.onWebTransportSession(value);
|
||||
}
|
||||
})();
|
||||
|
||||
h3Server.startServer();
|
||||
```
|
||||
|
||||
Added in [123b68c](https://github.com/socketio/engine.io/commit/123b68c04f9e971f59b526e0f967a488ee6b0116).
|
||||
|
||||
|
||||
#### Client bundles with CORS headers
|
||||
|
||||
The bundles will now have the right `Access-Control-Allow-xxx` headers.
|
||||
|
||||
Added in [63f181c](https://github.com/socketio/socket.io/commit/63f181cc12cbbbf94ed40eef52d60f36a1214fbe).
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
- [`engine.io@~6.4.2`](https://github.com/socketio/engine.io/releases/tag/6.5.0) ([diff](https://github.com/socketio/engine.io/compare/6.4.2...6.5.0))
|
||||
- [`ws@~8.11.0`](https://github.com/websockets/ws/releases/tag/8.11.0) (no change)
|
||||
|
||||
|
||||
|
||||
## [4.6.2](https://github.com/socketio/socket.io/compare/4.6.1...4.6.2) (2023-05-31)
|
||||
|
||||
|
||||
@@ -68,7 +155,7 @@
|
||||
|
||||
### Dependencies
|
||||
|
||||
- [`engine.io@~6.4.0`](https://github.com/socketio/engine.io/releases/tag/6.4.0) (no change)
|
||||
- [`engine.io@~6.4.2`](https://github.com/socketio/engine.io/releases/tag/6.4.0) ([diff](https://github.com/socketio/engine.io/compare/6.4.1...6.4.2))
|
||||
- [`ws@~8.11.0`](https://github.com/websockets/ws/releases/tag/8.11.0) (no change)
|
||||
|
||||
|
||||
@@ -84,7 +171,7 @@
|
||||
|
||||
### Dependencies
|
||||
|
||||
- [`engine.io@~6.4.0`](https://github.com/socketio/engine.io/releases/tag/6.4.0) (no change)
|
||||
- [`engine.io@~6.4.1`](https://github.com/socketio/engine.io/releases/tag/6.4.1) ([diff](https://github.com/socketio/engine.io/compare/6.4.0...6.4.1))
|
||||
- [`ws@~8.11.0`](https://github.com/websockets/ws/releases/tag/8.11.0) (no change)
|
||||
|
||||
|
||||
|
||||
4
client-dist/socket.io.esm.min.js
vendored
4
client-dist/socket.io.esm.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Socket.IO v4.6.2
|
||||
* Socket.IO v4.7.0
|
||||
* (c) 2014-2023 Guillermo Rauch
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
@@ -355,12 +355,40 @@
|
||||
|
||||
fileReader.onload = function () {
|
||||
var content = fileReader.result.split(",")[1];
|
||||
callback("b" + content);
|
||||
callback("b" + (content || ""));
|
||||
};
|
||||
|
||||
return fileReader.readAsDataURL(data);
|
||||
};
|
||||
|
||||
function toArray(data) {
|
||||
if (data instanceof Uint8Array) {
|
||||
return data;
|
||||
} else if (data instanceof ArrayBuffer) {
|
||||
return new Uint8Array(data);
|
||||
} else {
|
||||
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
||||
}
|
||||
}
|
||||
|
||||
var TEXT_ENCODER;
|
||||
function encodePacketToBinary(packet, callback) {
|
||||
if (withNativeBlob$1 && packet.data instanceof Blob) {
|
||||
return packet.data.arrayBuffer().then(toArray).then(callback);
|
||||
} else if (withNativeArrayBuffer$2 && (packet.data instanceof ArrayBuffer || isView$1(packet.data))) {
|
||||
return callback(toArray(packet.data));
|
||||
}
|
||||
|
||||
encodePacket(packet, false, function (encoded) {
|
||||
if (!TEXT_ENCODER) {
|
||||
TEXT_ENCODER = new TextEncoder();
|
||||
}
|
||||
|
||||
callback(TEXT_ENCODER.encode(encoded));
|
||||
});
|
||||
}
|
||||
|
||||
// imported from https://github.com/socketio/base64-arraybuffer
|
||||
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; // Use a lookup table to find the index.
|
||||
|
||||
var lookup$1 = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
|
||||
@@ -403,7 +431,6 @@
|
||||
};
|
||||
|
||||
var withNativeArrayBuffer$1 = typeof ArrayBuffer === "function";
|
||||
|
||||
var decodePacket = function decodePacket(encodedPacket, binaryType) {
|
||||
if (typeof encodedPacket !== "string") {
|
||||
return {
|
||||
@@ -450,12 +477,24 @@
|
||||
var mapBinary = function mapBinary(data, binaryType) {
|
||||
switch (binaryType) {
|
||||
case "blob":
|
||||
return data instanceof ArrayBuffer ? new Blob([data]) : data;
|
||||
if (data instanceof Blob) {
|
||||
// from WebSocket + binaryType "blob"
|
||||
return data;
|
||||
} else {
|
||||
// from HTTP long-polling or WebTransport
|
||||
return new Blob([data]);
|
||||
}
|
||||
|
||||
case "arraybuffer":
|
||||
default:
|
||||
return data;
|
||||
// assuming the data is already an ArrayBuffer
|
||||
if (data instanceof ArrayBuffer) {
|
||||
// from HTTP long-polling (base64) or WebSocket + binaryType "arraybuffer"
|
||||
return data;
|
||||
} else {
|
||||
// from WebTransport (Uint8Array)
|
||||
return data.buffer;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@@ -494,6 +533,18 @@
|
||||
return packets;
|
||||
};
|
||||
|
||||
var TEXT_DECODER;
|
||||
function decodePacketFromBinary(data, isBinary, binaryType) {
|
||||
if (!TEXT_DECODER) {
|
||||
// lazily created for compatibility with old browser platforms
|
||||
TEXT_DECODER = new TextDecoder();
|
||||
} // 48 === "0".charCodeAt(0) (OPEN packet type)
|
||||
// 54 === "6".charCodeAt(0) (NOOP packet type)
|
||||
|
||||
|
||||
var isPlainBinary = isBinary || data[0] < 48 || data[0] > 54;
|
||||
return decodePacket(isPlainBinary ? data : TEXT_DECODER.decode(data), binaryType);
|
||||
}
|
||||
var protocol$1 = 4;
|
||||
|
||||
/**
|
||||
@@ -728,6 +779,46 @@
|
||||
return length;
|
||||
}
|
||||
|
||||
// imported from https://github.com/galkn/querystring
|
||||
|
||||
/**
|
||||
* Compiles a querystring
|
||||
* Returns string representation of the object
|
||||
*
|
||||
* @param {Object}
|
||||
* @api private
|
||||
*/
|
||||
function encode$1(obj) {
|
||||
var str = '';
|
||||
|
||||
for (var i in obj) {
|
||||
if (obj.hasOwnProperty(i)) {
|
||||
if (str.length) str += '&';
|
||||
str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
/**
|
||||
* Parses a simple querystring into an object
|
||||
*
|
||||
* @param {String} qs
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function decode(qs) {
|
||||
var qry = {};
|
||||
var pairs = qs.split('&');
|
||||
|
||||
for (var i = 0, l = pairs.length; i < l; i++) {
|
||||
var pair = pairs[i].split('=');
|
||||
qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
|
||||
}
|
||||
|
||||
return qry;
|
||||
}
|
||||
|
||||
var TransportError = /*#__PURE__*/function (_Error) {
|
||||
_inherits(TransportError, _Error);
|
||||
|
||||
@@ -888,6 +979,33 @@
|
||||
}, {
|
||||
key: "pause",
|
||||
value: function pause(onPause) {}
|
||||
}, {
|
||||
key: "createUri",
|
||||
value: function createUri(schema) {
|
||||
var query = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||||
return schema + "://" + this._hostname() + this._port() + this.opts.path + this._query(query);
|
||||
}
|
||||
}, {
|
||||
key: "_hostname",
|
||||
value: function _hostname() {
|
||||
var hostname = this.opts.hostname;
|
||||
return hostname.indexOf(":") === -1 ? hostname : "[" + hostname + "]";
|
||||
}
|
||||
}, {
|
||||
key: "_port",
|
||||
value: function _port() {
|
||||
if (this.opts.port && (this.opts.secure && Number(this.opts.port !== 443) || !this.opts.secure && Number(this.opts.port) !== 80)) {
|
||||
return ":" + this.opts.port;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}, {
|
||||
key: "_query",
|
||||
value: function _query(query) {
|
||||
var encodedQuery = encode$1(query);
|
||||
return encodedQuery.length ? "?" + encodedQuery : "";
|
||||
}
|
||||
}]);
|
||||
|
||||
return Transport;
|
||||
@@ -909,7 +1027,7 @@
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function encode$1(num) {
|
||||
function encode(num) {
|
||||
var encoded = '';
|
||||
|
||||
do {
|
||||
@@ -927,9 +1045,9 @@
|
||||
*/
|
||||
|
||||
function yeast() {
|
||||
var now = encode$1(+new Date());
|
||||
var now = encode(+new Date());
|
||||
if (now !== prev) return seed = 0, prev = now;
|
||||
return now + '.' + encode$1(seed++);
|
||||
return now + '.' + encode(seed++);
|
||||
} //
|
||||
// Map each character to its index.
|
||||
//
|
||||
@@ -938,46 +1056,6 @@
|
||||
map[alphabet[i]] = i;
|
||||
}
|
||||
|
||||
// imported from https://github.com/galkn/querystring
|
||||
|
||||
/**
|
||||
* Compiles a querystring
|
||||
* Returns string representation of the object
|
||||
*
|
||||
* @param {Object}
|
||||
* @api private
|
||||
*/
|
||||
function encode(obj) {
|
||||
var str = '';
|
||||
|
||||
for (var i in obj) {
|
||||
if (obj.hasOwnProperty(i)) {
|
||||
if (str.length) str += '&';
|
||||
str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
/**
|
||||
* Parses a simple querystring into an object
|
||||
*
|
||||
* @param {String} qs
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function decode(qs) {
|
||||
var qry = {};
|
||||
var pairs = qs.split('&');
|
||||
|
||||
for (var i = 0, l = pairs.length; i < l; i++) {
|
||||
var pair = pairs[i].split('=');
|
||||
qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
|
||||
}
|
||||
|
||||
return qry;
|
||||
}
|
||||
|
||||
// imported from https://github.com/component/has-cors
|
||||
var value = false;
|
||||
|
||||
@@ -1005,6 +1083,7 @@
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
function createCookieJar() {}
|
||||
|
||||
function empty() {}
|
||||
|
||||
@@ -1043,7 +1122,6 @@
|
||||
}
|
||||
|
||||
_this.xd = typeof location !== "undefined" && opts.hostname !== location.hostname || port !== opts.port;
|
||||
_this.xs = opts.secure !== isSSL;
|
||||
}
|
||||
/**
|
||||
* XHR supports binary
|
||||
@@ -1052,6 +1130,11 @@
|
||||
|
||||
var forceBase64 = opts && opts.forceBase64;
|
||||
_this.supportsBinary = hasXHR2 && !forceBase64;
|
||||
|
||||
if (_this.opts.withCredentials) {
|
||||
_this.cookieJar = createCookieJar();
|
||||
}
|
||||
|
||||
return _this;
|
||||
}
|
||||
|
||||
@@ -1222,9 +1305,8 @@
|
||||
}, {
|
||||
key: "uri",
|
||||
value: function uri() {
|
||||
var query = this.query || {};
|
||||
var schema = this.opts.secure ? "https" : "http";
|
||||
var port = ""; // cache busting is forced
|
||||
var query = this.query || {}; // cache busting is forced
|
||||
|
||||
if (false !== this.opts.timestampRequests) {
|
||||
query[this.opts.timestampParam] = yeast();
|
||||
@@ -1232,16 +1314,9 @@
|
||||
|
||||
if (!this.supportsBinary && !query.sid) {
|
||||
query.b64 = 1;
|
||||
} // avoid port if default for schema
|
||||
|
||||
|
||||
if (this.opts.port && ("https" === schema && Number(this.opts.port) !== 443 || "http" === schema && Number(this.opts.port) !== 80)) {
|
||||
port = ":" + this.opts.port;
|
||||
}
|
||||
|
||||
var encodedQuery = encode(query);
|
||||
var ipv6 = this.opts.hostname.indexOf(":") !== -1;
|
||||
return schema + "://" + (ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) + port + this.opts.path + (encodedQuery.length ? "?" + encodedQuery : "");
|
||||
return this.createUri(schema, query);
|
||||
}
|
||||
/**
|
||||
* Creates a request.
|
||||
@@ -1257,7 +1332,7 @@
|
||||
|
||||
_extends(opts, {
|
||||
xd: this.xd,
|
||||
xs: this.xs
|
||||
cookieJar: this.cookieJar
|
||||
}, this.opts);
|
||||
|
||||
return new Request(this.uri(), opts);
|
||||
@@ -1327,7 +1402,6 @@
|
||||
_this8.opts = opts;
|
||||
_this8.method = opts.method || "GET";
|
||||
_this8.uri = uri;
|
||||
_this8.async = false !== opts.async;
|
||||
_this8.data = undefined !== opts.data ? opts.data : null;
|
||||
|
||||
_this8.create();
|
||||
@@ -1346,13 +1420,14 @@
|
||||
value: function create() {
|
||||
var _this9 = this;
|
||||
|
||||
var _a;
|
||||
|
||||
var opts = pick(this.opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
|
||||
opts.xdomain = !!this.opts.xd;
|
||||
opts.xscheme = !!this.opts.xs;
|
||||
var xhr = this.xhr = new XHR(opts);
|
||||
|
||||
try {
|
||||
xhr.open(this.method, this.uri, this.async);
|
||||
xhr.open(this.method, this.uri, true);
|
||||
|
||||
try {
|
||||
if (this.opts.extraHeaders) {
|
||||
@@ -1374,8 +1449,9 @@
|
||||
|
||||
try {
|
||||
xhr.setRequestHeader("Accept", "*/*");
|
||||
} catch (e) {} // ie6 check
|
||||
} catch (e) {}
|
||||
|
||||
(_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr); // ie6 check
|
||||
|
||||
if ("withCredentials" in xhr) {
|
||||
xhr.withCredentials = this.opts.withCredentials;
|
||||
@@ -1386,6 +1462,12 @@
|
||||
}
|
||||
|
||||
xhr.onreadystatechange = function () {
|
||||
var _a;
|
||||
|
||||
if (xhr.readyState === 3) {
|
||||
(_a = _this9.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(xhr);
|
||||
}
|
||||
|
||||
if (4 !== xhr.readyState) return;
|
||||
|
||||
if (200 === xhr.status || 1223 === xhr.status) {
|
||||
@@ -1675,14 +1757,8 @@
|
||||
}, {
|
||||
key: "uri",
|
||||
value: function uri() {
|
||||
var query = this.query || {};
|
||||
var schema = this.opts.secure ? "wss" : "ws";
|
||||
var port = ""; // avoid port if default for schema
|
||||
|
||||
if (this.opts.port && ("wss" === schema && Number(this.opts.port) !== 443 || "ws" === schema && Number(this.opts.port) !== 80)) {
|
||||
port = ":" + this.opts.port;
|
||||
} // append timestamp to URI
|
||||
|
||||
var query = this.query || {}; // append timestamp to URI
|
||||
|
||||
if (this.opts.timestampRequests) {
|
||||
query[this.opts.timestampParam] = yeast();
|
||||
@@ -1693,9 +1769,7 @@
|
||||
query.b64 = 1;
|
||||
}
|
||||
|
||||
var encodedQuery = encode(query);
|
||||
var ipv6 = this.opts.hostname.indexOf(":") !== -1;
|
||||
return schema + "://" + (ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) + port + this.opts.path + (encodedQuery.length ? "?" + encodedQuery : "");
|
||||
return this.createUri(schema, query);
|
||||
}
|
||||
/**
|
||||
* Feature detection for WebSocket.
|
||||
@@ -1714,8 +1788,127 @@
|
||||
return WS;
|
||||
}(Transport);
|
||||
|
||||
function shouldIncludeBinaryHeader(packet, encoded) {
|
||||
// 48 === "0".charCodeAt(0) (OPEN packet type)
|
||||
// 54 === "6".charCodeAt(0) (NOOP packet type)
|
||||
return packet.type === "message" && typeof packet.data !== "string" && encoded[0] >= 48 && encoded[0] <= 54;
|
||||
}
|
||||
|
||||
var WT = /*#__PURE__*/function (_Transport) {
|
||||
_inherits(WT, _Transport);
|
||||
|
||||
var _super = _createSuper(WT);
|
||||
|
||||
function WT() {
|
||||
_classCallCheck(this, WT);
|
||||
|
||||
return _super.apply(this, arguments);
|
||||
}
|
||||
|
||||
_createClass(WT, [{
|
||||
key: "name",
|
||||
get: function get() {
|
||||
return "webtransport";
|
||||
}
|
||||
}, {
|
||||
key: "doOpen",
|
||||
value: function doOpen() {
|
||||
var _this = this;
|
||||
|
||||
// @ts-ignore
|
||||
if (typeof WebTransport !== "function") {
|
||||
return;
|
||||
} // @ts-ignore
|
||||
|
||||
|
||||
this.transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
|
||||
this.transport.closed.then(function () {
|
||||
return _this.onClose();
|
||||
}); // note: we could have used async/await, but that would require some additional polyfills
|
||||
|
||||
this.transport.ready.then(function () {
|
||||
_this.transport.createBidirectionalStream().then(function (stream) {
|
||||
var reader = stream.readable.getReader();
|
||||
_this.writer = stream.writable.getWriter();
|
||||
var binaryFlag;
|
||||
|
||||
var read = function read() {
|
||||
reader.read().then(function (_ref) {
|
||||
var done = _ref.done,
|
||||
value = _ref.value;
|
||||
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!binaryFlag && value.byteLength === 1 && value[0] === 54) {
|
||||
binaryFlag = true;
|
||||
} else {
|
||||
// TODO expose binarytype
|
||||
_this.onPacket(decodePacketFromBinary(value, binaryFlag, "arraybuffer"));
|
||||
|
||||
binaryFlag = false;
|
||||
}
|
||||
|
||||
read();
|
||||
});
|
||||
};
|
||||
|
||||
read();
|
||||
var handshake = _this.query.sid ? "0{\"sid\":\"".concat(_this.query.sid, "\"}") : "0";
|
||||
|
||||
_this.writer.write(new TextEncoder().encode(handshake)).then(function () {
|
||||
return _this.onOpen();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: "write",
|
||||
value: function write(packets) {
|
||||
var _this2 = this;
|
||||
|
||||
this.writable = false;
|
||||
|
||||
var _loop = function _loop(i) {
|
||||
var packet = packets[i];
|
||||
var lastPacket = i === packets.length - 1;
|
||||
encodePacketToBinary(packet, function (data) {
|
||||
if (shouldIncludeBinaryHeader(packet, data)) {
|
||||
_this2.writer.write(Uint8Array.of(54));
|
||||
}
|
||||
|
||||
_this2.writer.write(data).then(function () {
|
||||
if (lastPacket) {
|
||||
nextTick(function () {
|
||||
_this2.writable = true;
|
||||
|
||||
_this2.emitReserved("drain");
|
||||
}, _this2.setTimeoutFn);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
for (var i = 0; i < packets.length; i++) {
|
||||
_loop(i);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
key: "doClose",
|
||||
value: function doClose() {
|
||||
var _a;
|
||||
|
||||
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.close();
|
||||
}
|
||||
}]);
|
||||
|
||||
return WT;
|
||||
}(Transport);
|
||||
|
||||
var transports = {
|
||||
websocket: WS,
|
||||
webtransport: WT,
|
||||
polling: Polling
|
||||
};
|
||||
|
||||
@@ -1841,7 +2034,7 @@
|
||||
|
||||
_this.hostname = opts.hostname || (typeof location !== "undefined" ? location.hostname : "localhost");
|
||||
_this.port = opts.port || (typeof location !== "undefined" && location.port ? location.port : _this.secure ? "443" : "80");
|
||||
_this.transports = opts.transports || ["polling", "websocket"];
|
||||
_this.transports = opts.transports || ["polling", "websocket", "webtransport"];
|
||||
_this.writeBuffer = [];
|
||||
_this.prevBufferLen = 0;
|
||||
_this.opts = _extends({
|
||||
@@ -2108,7 +2301,17 @@
|
||||
transport.once("close", onTransportClose);
|
||||
this.once("close", onclose);
|
||||
this.once("upgrading", onupgrade);
|
||||
transport.open();
|
||||
|
||||
if (this.upgrades.indexOf("webtransport") !== -1 && name !== "webtransport") {
|
||||
// favor WebTransport
|
||||
this.setTimeoutFn(function () {
|
||||
if (!failed) {
|
||||
transport.open();
|
||||
}
|
||||
}, 200);
|
||||
} else {
|
||||
transport.open();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Called when connection is deemed open.
|
||||
@@ -4381,11 +4584,12 @@
|
||||
var openSubDestroy = on(socket, "open", function () {
|
||||
self.onopen();
|
||||
fn && fn();
|
||||
}); // emit `error`
|
||||
});
|
||||
|
||||
var errorSub = on(socket, "error", function (err) {
|
||||
self.cleanup();
|
||||
self._readyState = "closed";
|
||||
var onError = function onError(err) {
|
||||
_this2.cleanup();
|
||||
|
||||
_this2._readyState = "closed";
|
||||
|
||||
_this2.emitReserved("error", err);
|
||||
|
||||
@@ -4393,31 +4597,28 @@
|
||||
fn(err);
|
||||
} else {
|
||||
// Only do this if there is no fn to handle the error
|
||||
self.maybeReconnectOnOpen();
|
||||
_this2.maybeReconnectOnOpen();
|
||||
}
|
||||
});
|
||||
}; // emit `error`
|
||||
|
||||
|
||||
var errorSub = on(socket, "error", onError);
|
||||
|
||||
if (false !== this._timeout) {
|
||||
var timeout = this._timeout;
|
||||
|
||||
if (timeout === 0) {
|
||||
openSubDestroy(); // prevents a race condition with the 'open' event
|
||||
} // set timer
|
||||
|
||||
var timeout = this._timeout; // set timer
|
||||
|
||||
var timer = this.setTimeoutFn(function () {
|
||||
openSubDestroy();
|
||||
socket.close(); // @ts-ignore
|
||||
|
||||
socket.emit("error", new Error("timeout"));
|
||||
onError(new Error("timeout"));
|
||||
socket.close();
|
||||
}, timeout);
|
||||
|
||||
if (this.opts.autoUnref) {
|
||||
timer.unref();
|
||||
}
|
||||
|
||||
this.subs.push(function subDestroy() {
|
||||
clearTimeout(timer);
|
||||
this.subs.push(function () {
|
||||
_this2.clearTimeoutFn(timer);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4670,8 +4871,8 @@
|
||||
timer.unref();
|
||||
}
|
||||
|
||||
this.subs.push(function subDestroy() {
|
||||
clearTimeout(timer);
|
||||
this.subs.push(function () {
|
||||
_this4.clearTimeoutFn(timer);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
4
client-dist/socket.io.min.js
vendored
4
client-dist/socket.io.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
client-dist/socket.io.msgpack.min.js
vendored
4
client-dist/socket.io.msgpack.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -51,4 +51,5 @@ RewriteRule /(.*) balancer://nodes_ws/$1 [P,L]
|
||||
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
|
||||
RewriteRule /(.*) balancer://nodes_polling/$1 [P,L]
|
||||
|
||||
ProxyTimeout 3
|
||||
# must be bigger than pingInterval (25s by default) + pingTimeout (20s by default)
|
||||
ProxyTimeout 60
|
||||
|
||||
18
lib/index.ts
18
lib/index.ts
@@ -40,6 +40,7 @@ import {
|
||||
SecondArg,
|
||||
} from "./typed-events";
|
||||
import { patchAdapter, restoreAdapter, serveFile } from "./uws";
|
||||
import corsMiddleware from "cors";
|
||||
|
||||
const debug = debugModule("socket.io:server");
|
||||
|
||||
@@ -202,6 +203,11 @@ export class Server<
|
||||
*/
|
||||
_connectTimeout: number;
|
||||
private httpServer: http.Server | HTTPSServer | Http2SecureServer;
|
||||
private _corsMiddleware: (
|
||||
req: http.IncomingMessage,
|
||||
res: http.ServerResponse,
|
||||
next: () => void
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* Server constructor.
|
||||
@@ -267,6 +273,10 @@ export class Server<
|
||||
this.attach(
|
||||
srv as http.Server | HTTPSServer | Http2SecureServer | number
|
||||
);
|
||||
|
||||
if (this.opts.cors) {
|
||||
this._corsMiddleware = corsMiddleware(this.opts.cors);
|
||||
}
|
||||
}
|
||||
|
||||
get _opts() {
|
||||
@@ -548,7 +558,13 @@ export class Server<
|
||||
srv.removeAllListeners("request");
|
||||
srv.on("request", (req, res) => {
|
||||
if (this.clientPathRegex.test(req.url!)) {
|
||||
this.serve(req, res);
|
||||
if (this._corsMiddleware) {
|
||||
this._corsMiddleware(req, res, () => {
|
||||
this.serve(req, res);
|
||||
});
|
||||
} else {
|
||||
this.serve(req, res);
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < evs.length; i++) {
|
||||
evs[i].call(srv, req, res);
|
||||
|
||||
@@ -202,7 +202,7 @@ export class Socket<
|
||||
* Additional information that can be attached to the Socket instance and which will be used in the
|
||||
* {@link Server.fetchSockets()} method.
|
||||
*/
|
||||
public data: Partial<SocketData> = {};
|
||||
public data: SocketData = {} as SocketData;
|
||||
/**
|
||||
* Whether the socket is currently connected or not.
|
||||
*
|
||||
@@ -260,7 +260,7 @@ export class Socket<
|
||||
this.id = previousSession.sid;
|
||||
this.pid = previousSession.pid;
|
||||
previousSession.rooms.forEach((room) => this.join(room));
|
||||
this.data = previousSession.data as Partial<SocketData>;
|
||||
this.data = previousSession.data as SocketData;
|
||||
previousSession.missedPackets.forEach((packet) => {
|
||||
this.packet({
|
||||
type: PacketType.EVENT,
|
||||
|
||||
75
package-lock.json
generated
75
package-lock.json
generated
@@ -11,8 +11,9 @@
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "~2.0.0",
|
||||
"cors": "~2.8.5",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io": "~6.4.2",
|
||||
"engine.io": "~6.5.0",
|
||||
"socket.io-adapter": "~2.5.2",
|
||||
"socket.io-parser": "~4.2.4"
|
||||
},
|
||||
@@ -23,14 +24,14 @@
|
||||
"nyc": "^15.1.0",
|
||||
"prettier": "^2.3.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"socket.io-client": "4.6.2",
|
||||
"socket.io-client": "4.7.0",
|
||||
"socket.io-client-v2": "npm:socket.io-client@^2.4.0",
|
||||
"superagent": "^8.0.0",
|
||||
"supertest": "^6.1.6",
|
||||
"ts-node": "^10.2.1",
|
||||
"tsd": "^0.21.0",
|
||||
"typescript": "^4.4.2",
|
||||
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.0.0"
|
||||
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.30.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
@@ -1377,9 +1378,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/engine.io": {
|
||||
"version": "6.4.2",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.2.tgz",
|
||||
"integrity": "sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.0.tgz",
|
||||
"integrity": "sha512-UlfoK1iD62Hkedw2TmuHdhDsZCGaAyp+LZ/AvnImjYBeWagA3qIEETum90d6shMeFZiDuGT66zVCdx1wKYKGGg==",
|
||||
"dependencies": {
|
||||
"@types/cookie": "^0.4.1",
|
||||
"@types/cors": "^2.8.12",
|
||||
@@ -1389,7 +1390,7 @@
|
||||
"cookie": "~0.4.1",
|
||||
"cors": "~2.8.5",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.0.3",
|
||||
"engine.io-parser": "~5.1.0",
|
||||
"ws": "~8.11.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1397,22 +1398,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-client": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz",
|
||||
"integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.0.tgz",
|
||||
"integrity": "sha512-C7eN3OKggSfd5g8IDgUA9guC8TNS6CEganKT7dL6Fp3q+FobcQ/WBn2Qq2XTL1vNTiFZfDzXohvqLuR9dWejdg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.0.3",
|
||||
"engine.io-parser": "~5.1.0",
|
||||
"ws": "~8.11.0",
|
||||
"xmlhttprequest-ssl": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-parser": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz",
|
||||
"integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.1.0.tgz",
|
||||
"integrity": "sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
@@ -3463,14 +3464,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-client": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.2.tgz",
|
||||
"integrity": "sha512-OwWrMbbA8wSqhBAR0yoPK6EdQLERQAYjXb3A0zLpgxfM1ZGLKoxHx8gVmCHA6pcclRX5oA/zvQf7bghAS11jRA==",
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.0.tgz",
|
||||
"integrity": "sha512-7Q8CeDrhuZzg4QLXl3tXlk5yb086oxYzehAVZRLiGCzCmtDneiHz1qHyyWcxhTgxXiokVpWQXoG/u60HoXSQew==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io-client": "~6.4.0",
|
||||
"engine.io-client": "~6.5.0",
|
||||
"socket.io-parser": "~4.2.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -4105,8 +4106,8 @@
|
||||
}
|
||||
},
|
||||
"node_modules/uWebSockets.js": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "git+https://git@github.com/uNetworking/uWebSockets.js.git#4558ee00f9f1f686fffe1accbfc2e85b1af9c50f",
|
||||
"version": "20.30.0",
|
||||
"resolved": "git+https://git@github.com/uNetworking/uWebSockets.js.git#d39d4181daf5b670d44cbc1b18f8c28c85fd4142",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/v8-compile-cache-lib": {
|
||||
@@ -5387,9 +5388,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"engine.io": {
|
||||
"version": "6.4.2",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.2.tgz",
|
||||
"integrity": "sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.0.tgz",
|
||||
"integrity": "sha512-UlfoK1iD62Hkedw2TmuHdhDsZCGaAyp+LZ/AvnImjYBeWagA3qIEETum90d6shMeFZiDuGT66zVCdx1wKYKGGg==",
|
||||
"requires": {
|
||||
"@types/cookie": "^0.4.1",
|
||||
"@types/cors": "^2.8.12",
|
||||
@@ -5399,27 +5400,27 @@
|
||||
"cookie": "~0.4.1",
|
||||
"cors": "~2.8.5",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.0.3",
|
||||
"engine.io-parser": "~5.1.0",
|
||||
"ws": "~8.11.0"
|
||||
}
|
||||
},
|
||||
"engine.io-client": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz",
|
||||
"integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.0.tgz",
|
||||
"integrity": "sha512-C7eN3OKggSfd5g8IDgUA9guC8TNS6CEganKT7dL6Fp3q+FobcQ/WBn2Qq2XTL1vNTiFZfDzXohvqLuR9dWejdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.0.3",
|
||||
"engine.io-parser": "~5.1.0",
|
||||
"ws": "~8.11.0",
|
||||
"xmlhttprequest-ssl": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"engine.io-parser": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz",
|
||||
"integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg=="
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.1.0.tgz",
|
||||
"integrity": "sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w=="
|
||||
},
|
||||
"error-ex": {
|
||||
"version": "1.3.2",
|
||||
@@ -6922,14 +6923,14 @@
|
||||
}
|
||||
},
|
||||
"socket.io-client": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.2.tgz",
|
||||
"integrity": "sha512-OwWrMbbA8wSqhBAR0yoPK6EdQLERQAYjXb3A0zLpgxfM1ZGLKoxHx8gVmCHA6pcclRX5oA/zvQf7bghAS11jRA==",
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.0.tgz",
|
||||
"integrity": "sha512-7Q8CeDrhuZzg4QLXl3tXlk5yb086oxYzehAVZRLiGCzCmtDneiHz1qHyyWcxhTgxXiokVpWQXoG/u60HoXSQew==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io-client": "~6.4.0",
|
||||
"engine.io-client": "~6.5.0",
|
||||
"socket.io-parser": "~4.2.4"
|
||||
}
|
||||
},
|
||||
@@ -7402,9 +7403,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"uWebSockets.js": {
|
||||
"version": "git+https://git@github.com/uNetworking/uWebSockets.js.git#4558ee00f9f1f686fffe1accbfc2e85b1af9c50f",
|
||||
"version": "git+https://git@github.com/uNetworking/uWebSockets.js.git#d39d4181daf5b670d44cbc1b18f8c28c85fd4142",
|
||||
"dev": true,
|
||||
"from": "uWebSockets.js@github:uNetworking/uWebSockets.js#v20.0.0"
|
||||
"from": "uWebSockets.js@github:uNetworking/uWebSockets.js#v20.30.0"
|
||||
},
|
||||
"v8-compile-cache-lib": {
|
||||
"version": "3.0.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "socket.io",
|
||||
"version": "4.6.2",
|
||||
"version": "4.7.0",
|
||||
"description": "node.js realtime framework server",
|
||||
"keywords": [
|
||||
"realtime",
|
||||
@@ -48,8 +48,9 @@
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "~2.0.0",
|
||||
"cors": "~2.8.5",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io": "~6.4.2",
|
||||
"engine.io": "~6.5.0",
|
||||
"socket.io-adapter": "~2.5.2",
|
||||
"socket.io-parser": "~4.2.4"
|
||||
},
|
||||
@@ -60,14 +61,14 @@
|
||||
"nyc": "^15.1.0",
|
||||
"prettier": "^2.3.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"socket.io-client": "4.6.2",
|
||||
"socket.io-client": "4.7.0",
|
||||
"socket.io-client-v2": "npm:socket.io-client@^2.4.0",
|
||||
"superagent": "^8.0.0",
|
||||
"supertest": "^6.1.6",
|
||||
"ts-node": "^10.2.1",
|
||||
"tsd": "^0.21.0",
|
||||
"typescript": "^4.4.2",
|
||||
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.0.0"
|
||||
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.30.0"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
|
||||
@@ -70,6 +70,27 @@ describe("server attachment", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should serve client with necessary CORS headers", (done) => {
|
||||
const srv = createServer();
|
||||
new Server(srv, {
|
||||
cors: {
|
||||
origin: "https://good-origin.com",
|
||||
},
|
||||
});
|
||||
request(srv)
|
||||
.get("/socket.io/socket.io.js")
|
||||
.set("origin", "https://good-origin.com")
|
||||
.buffer(true)
|
||||
.end((err, res) => {
|
||||
if (err) return done(err);
|
||||
expect(res.headers["access-control-allow-origin"]).to.be(
|
||||
"https://good-origin.com"
|
||||
);
|
||||
expect(res.status).to.be(200);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it(
|
||||
"should serve bundle with msgpack parser",
|
||||
testSource("socket.io.msgpack.min.js")
|
||||
|
||||
@@ -852,10 +852,6 @@ describe("socket", () => {
|
||||
it("should not crash when messing with Object prototype (and other globals)", (done) => {
|
||||
// @ts-ignore
|
||||
Object.prototype.foo = "bar";
|
||||
// @ts-ignore
|
||||
global.File = "";
|
||||
// @ts-ignore
|
||||
global.Blob = [];
|
||||
const io = new Server(0);
|
||||
const socket = createClient(io);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user