diff --git a/History.md b/History.md index 1491b8ce2b..bd0cbf4715 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +0.9.19-overleaf-10 / 2023-04-25 +=============================== + +* Overleaf: Add support for Node 18 by gracefully handling `req.socket == null`. + 0.9.19-overleaf-9 / 2022-08-18 ============================== diff --git a/lib/manager.js b/lib/manager.js index d3ccf1a842..95dc9b5e38 100644 --- a/lib/manager.js +++ b/lib/manager.js @@ -115,7 +115,21 @@ function Manager (server, options) { server.removeAllListeners('request'); server.on('request', function (req, res) { - self.handleRequest(req, res); + var socket = req.socket; + if (!socket) { + // aborted request + self.log.warn('bail out from aborted request (req.socket missing)'); + // nginx uses status code 499 when clients close the connection before a response could be sent. + // https://github.com/nginx/nginx/blob/bfc5b35827903a3c543b58e4562db8b62021c164/src/http/ngx_http_request.h#L128-L134 + try { + res.writeHead(499); + res.end(); + } catch (e) { + self.log.warn('cannot reply to aborted request: ' + e.message); + } + return; + } + self.handleRequest(req, res, socket); }); server.on('upgrade', function (req, socket, head) { @@ -579,7 +593,7 @@ Manager.prototype.onDisconnect = function (id) { * @api private */ -Manager.prototype.handleRequest = function (req, res) { +Manager.prototype.handleRequest = function (req, res, socket) { var data = this.checkRequest(req); if (!data) { @@ -610,9 +624,9 @@ Manager.prototype.handleRequest = function (req, res) { this.log.info('client protocol version unsupported'); } else { if (data.id) { - this.handleHTTPRequest(data, req, res); + this.handleHTTPRequest(data, req, res, socket); } else { - this.handleHandshake(data, req, res); + this.handleHandshake(data, req, res, socket); } } }; @@ -637,7 +651,7 @@ Manager.prototype.handleUpgrade = function (req, socket, head) { } req.head = head; - this.handleClient(data, req); + this.handleClient(data, req, socket); req.head = null; }; @@ -647,9 +661,9 @@ Manager.prototype.handleUpgrade = function (req, socket, head) { * @api private */ -Manager.prototype.handleHTTPRequest = function (data, req, res) { +Manager.prototype.handleHTTPRequest = function (data, req, res, socket) { req.res = res; - this.handleClient(data, req); + this.handleClient(data, req, socket); }; /** @@ -658,11 +672,7 @@ Manager.prototype.handleHTTPRequest = function (data, req, res) { * @api private */ -Manager.prototype.handleClient = function (data, req) { - var socket = req.socket - , store = this.store - , self = this; - +Manager.prototype.handleClient = function (data, req, socket) { // handle sync disconnect xhrs if (undefined != data.query.disconnect) { if (this.transports[data.id] && this.transports[data.id].open) { @@ -677,16 +687,16 @@ Manager.prototype.handleClient = function (data, req) { if (!~this.get('transports').indexOf(data.transport)) { this.log.warn('unknown transport: "' + data.transport + '"'); - req.connection.end(); + socket.end(); return; } - var transport = new transports[data.transport](this, data, req) + var transport = new transports[data.transport](this, data, req, socket) , handshaken = this.handshaken[data.id]; if (transport.disconnected) { // failed during transport setup - req.connection.end(); + socket.end(); return; } if (handshaken) { @@ -713,7 +723,7 @@ Manager.prototype.handleClient = function (data, req) { // initialize the socket for all namespaces for (var i in this.namespaces) { if (this.namespaces.hasOwnProperty(i)) { - var socket = this.namespaces[i].socket(data.id, true); + this.namespaces[i].socket(data.id, true); // echo back connect packet and fire connection event if (i === '') { @@ -762,7 +772,7 @@ Manager.prototype.generateId = function () { * @api private */ -Manager.prototype.handleHandshake = function (data, req, res) { +Manager.prototype.handleHandshake = function (data, req, res, socket) { var self = this , origin = req.headers.origin , headers = { @@ -789,7 +799,7 @@ Manager.prototype.handleHandshake = function (data, req, res) { return; } - var handshakeData = this.handshakeData(data); + var handshakeData = this.handshakeData(data, socket); if (origin) { // https://developer.mozilla.org/En/HTTP_Access_Control @@ -835,9 +845,8 @@ Manager.prototype.handleHandshake = function (data, req, res) { * @api private */ -Manager.prototype.handshakeData = function (data) { - var connection = data.request.connection - , connectionAddress +Manager.prototype.handshakeData = function (data, connection) { + var connectionAddress , date = new Date; if (connection.remoteAddress) { @@ -859,7 +868,7 @@ Manager.prototype.handshakeData = function (data) { , query: data.query , url: data.request.url , xdomain: !!data.request.headers.origin - , secure: data.request.connection.secure + , secure: connection.secure , issued: +date }; }; diff --git a/lib/socket.io.js b/lib/socket.io.js index 0016ebf27c..bee950f2ac 100644 --- a/lib/socket.io.js +++ b/lib/socket.io.js @@ -16,7 +16,7 @@ * Version. */ -exports.version = '0.9.19-overleaf-4'; +exports.version = '0.9.19-overleaf-10'; /** * Supported protocol version. diff --git a/lib/transport.js b/lib/transport.js index e04d2aee2d..79a1851828 100644 --- a/lib/transport.js +++ b/lib/transport.js @@ -23,12 +23,12 @@ exports = module.exports = Transport; * @api public */ -function Transport (mng, data, req) { +function Transport (mng, data, req, socket) { this.manager = mng; this.id = data.id; this.disconnected = false; this.drained = true; - this.handleRequest(req); + this.handleRequest(req, socket); }; /** @@ -57,12 +57,12 @@ Transport.prototype.__defineGetter__('store', function () { * @api private */ -Transport.prototype.handleRequest = function (req) { +Transport.prototype.handleRequest = function (req, socket) { this.log.debug('setting request', req.method, req.url); this.req = req; if (req.method == 'GET') { - this.socket = req.socket; + this.socket = socket; this.open = true; this.drained = true; this.setHeartbeatInterval(); diff --git a/lib/transports/flashsocket.js b/lib/transports/flashsocket.js index 35daa85e39..21b9aa2c80 100644 --- a/lib/transports/flashsocket.js +++ b/lib/transports/flashsocket.js @@ -42,8 +42,8 @@ exports = module.exports = FlashSocket; * @api public */ -function FlashSocket (mng, data, req) { - return WebSocket.call(this, mng, data, req); +function FlashSocket (mng, data, req, socket) { + return WebSocket.call(this, mng, data, req, socket); } /** diff --git a/lib/transports/htmlfile.js b/lib/transports/htmlfile.js index fce0c0ed56..6efeb732db 100644 --- a/lib/transports/htmlfile.js +++ b/lib/transports/htmlfile.js @@ -23,8 +23,8 @@ exports = module.exports = HTMLFile; * @api public */ -function HTMLFile (mng, data, req) { - HTTPTransport.call(this, mng, data, req); +function HTMLFile (mng, data, req, socket) { + HTTPTransport.call(this, mng, data, req, socket); }; /** @@ -47,8 +47,8 @@ HTMLFile.prototype.name = 'htmlfile'; * @api private */ -HTMLFile.prototype.handleRequest = function (req) { - HTTPTransport.prototype.handleRequest.call(this, req); +HTMLFile.prototype.handleRequest = function (req, socket) { + HTTPTransport.prototype.handleRequest.call(this, req, socket); if (req.method == 'GET') { req.res.writeHead(200, { diff --git a/lib/transports/http-polling.js b/lib/transports/http-polling.js index 89b7e0428b..cd4b673b72 100644 --- a/lib/transports/http-polling.js +++ b/lib/transports/http-polling.js @@ -23,8 +23,8 @@ exports = module.exports = HTTPPolling; * @api public. */ -function HTTPPolling (mng, data, req) { - HTTPTransport.call(this, mng, data, req); +function HTTPPolling (mng, data, req, socket) { + HTTPTransport.call(this, mng, data, req, socket); }; /** @@ -69,8 +69,8 @@ HTTPPolling.prototype.setHeartbeatInterval = function () { * @api private */ -HTTPPolling.prototype.handleRequest = function (req) { - HTTPTransport.prototype.handleRequest.call(this, req); +HTTPPolling.prototype.handleRequest = function (req, socket) { + HTTPTransport.prototype.handleRequest.call(this, req, socket); if (req.method == 'GET') { var self = this; diff --git a/lib/transports/http.js b/lib/transports/http.js index fa94b5975f..dc17668b26 100644 --- a/lib/transports/http.js +++ b/lib/transports/http.js @@ -25,8 +25,8 @@ exports = module.exports = HTTPTransport; * @api public */ -function HTTPTransport (mng, data, req) { - Transport.call(this, mng, data, req); +function HTTPTransport (mng, data, req, socket) { + Transport.call(this, mng, data, req, socket); }; /** @@ -41,7 +41,7 @@ HTTPTransport.prototype.__proto__ = Transport.prototype; * @api private */ -HTTPTransport.prototype.handleRequest = function (req) { +HTTPTransport.prototype.handleRequest = function (req, socket) { // Always set the response in case an error is returned to the client this.response = req.res; @@ -58,7 +58,11 @@ HTTPTransport.prototype.handleRequest = function (req) { if (Buffer.byteLength(buffer) >= self.manager.get('destroy buffer size')) { buffer = ''; - req.connection.destroy(); + if (socket.destroy) { + socket.destroy(); + } else if (socket.end) { + socket.end(); + } } }); @@ -82,7 +86,7 @@ HTTPTransport.prototype.handleRequest = function (req) { headers['X-XSS-Protection'] = '0'; } } else { - Transport.prototype.handleRequest.call(this, req); + Transport.prototype.handleRequest.call(this, req, socket); } }; diff --git a/lib/transports/jsonp-polling.js b/lib/transports/jsonp-polling.js index ad7d5aff3c..2d01eb1c87 100644 --- a/lib/transports/jsonp-polling.js +++ b/lib/transports/jsonp-polling.js @@ -24,8 +24,8 @@ exports = module.exports = JSONPPolling; * @api public */ -function JSONPPolling (mng, data, req) { - HTTPPolling.call(this, mng, data, req); +function JSONPPolling (mng, data, req, socket) { + HTTPPolling.call(this, mng, data, req, socket); this.head = 'io.j[0]('; this.foot = ');'; diff --git a/lib/transports/websocket.js b/lib/transports/websocket.js index 78a43043d5..fb3606ccd1 100644 --- a/lib/transports/websocket.js +++ b/lib/transports/websocket.js @@ -24,13 +24,13 @@ exports = module.exports = WebSocket; * @api public */ -function WebSocket (mng, data, req) { +function WebSocket (mng, data, req, socket) { var transport , version = req.headers['sec-websocket-version']; if (typeof version !== 'undefined' && typeof protocolVersions[version] !== 'undefined') { - transport = new protocolVersions[version](mng, data, req); + transport = new protocolVersions[version](mng, data, req, socket); } - else transport = new protocolVersions['default'](mng, data, req); + else transport = new protocolVersions['default'](mng, data, req, socket); if (typeof this.name !== 'undefined') transport.name = this.name; return transport; }; diff --git a/lib/transports/websocket/default.js b/lib/transports/websocket/default.js index 4ddb5f6c13..84b78eef1d 100644 --- a/lib/transports/websocket/default.js +++ b/lib/transports/websocket/default.js @@ -26,7 +26,7 @@ exports = module.exports = WebSocket; * @api public */ -function WebSocket (mng, data, req) { +function WebSocket (mng, data, req, socket) { // parser var self = this; @@ -47,7 +47,7 @@ function WebSocket (mng, data, req) { self.end(); }); - Transport.call(this, mng, data, req); + Transport.call(this, mng, data, req, socket); }; /** diff --git a/lib/transports/websocket/hybi-07-12.js b/lib/transports/websocket/hybi-07-12.js index 7bff6ff344..fcc2d24615 100644 --- a/lib/transports/websocket/hybi-07-12.js +++ b/lib/transports/websocket/hybi-07-12.js @@ -30,7 +30,7 @@ exports.Parser = Parser; * @api public */ -function WebSocket (mng, data, req) { +function WebSocket (mng, data, req, socket) { // parser var self = this; @@ -62,7 +62,7 @@ function WebSocket (mng, data, req) { self.end(); }); - Transport.call(this, mng, data, req); + Transport.call(this, mng, data, req, socket); }; /** diff --git a/lib/transports/websocket/hybi-16.js b/lib/transports/websocket/hybi-16.js index e572bc40cb..1dfb6d0988 100644 --- a/lib/transports/websocket/hybi-16.js +++ b/lib/transports/websocket/hybi-16.js @@ -29,7 +29,7 @@ exports.Parser = Parser; * @api public */ -function WebSocket (mng, data, req) { +function WebSocket (mng, data, req, socket) { // parser var self = this; @@ -61,7 +61,7 @@ function WebSocket (mng, data, req) { self.end(); }); - Transport.call(this, mng, data, req); + Transport.call(this, mng, data, req, socket); }; /** diff --git a/lib/transports/xhr-polling.js b/lib/transports/xhr-polling.js index 1db5aeee0f..3c9a7cb5f2 100644 --- a/lib/transports/xhr-polling.js +++ b/lib/transports/xhr-polling.js @@ -23,8 +23,8 @@ exports = module.exports = XHRPolling; * @api public */ -function XHRPolling (mng, data, req) { - HTTPPolling.call(this, mng, data, req); +function XHRPolling (mng, data, req, socket) { + HTTPPolling.call(this, mng, data, req, socket); }; /** diff --git a/package.json b/package.json index 819bf101b7..cc884209ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socket.io" - , "version": "0.9.19-overleaf-9" + , "version": "0.9.19-overleaf-10" , "description": "Real-time apps made cross-browser & easy with a WebSocket-like API" , "homepage": "http://socket.io" , "keywords": ["websocket", "socket", "realtime", "socket.io", "comet", "ajax"] diff --git a/support/node-websocket-client/lib/websocket.js b/support/node-websocket-client/lib/websocket.js index 4f7f73425c..33910b38b0 100644 --- a/support/node-websocket-client/lib/websocket.js +++ b/support/node-websocket-client/lib/websocket.js @@ -506,7 +506,7 @@ var WebSocket = function(url, proto, opts) { var data = undefined; return function(req, s, head) { - req.socket.setNoDelay(true); + if (req.socket) req.socket.setNoDelay(true); stream = s; if (readyState == CLOSED) {