From 13c9ebccca9c7bee80f4b9c1da4c128435d9dac1 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Wed, 19 Dec 2018 15:55:58 +0300 Subject: Node.js: changed the 'data' event calling sequence for the request. The problem is caused by Promises' inconsistency. The 'date' event could have been triggered before the user has started listening for it. To resolve the issue, we override the 'on' method of the request's emitter. --- src/nodejs/unit-http/http_server.js | 40 +++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'src/nodejs') diff --git a/src/nodejs/unit-http/http_server.js b/src/nodejs/unit-http/http_server.js index 47851c98..9b7b8403 100755 --- a/src/nodejs/unit-http/http_server.js +++ b/src/nodejs/unit-http/http_server.js @@ -288,6 +288,28 @@ ServerRequest.prototype.resume = function resume() { return []; }; +/* + * The "on" method is overridden to defer reading data until user code is + * ready, that is (ev === "data"). This can occur after req.emit("end") is + * executed, since the user code can be scheduled asynchronously by Promises + * and so on. Passing the data is postponed by process.nextTick() until + * the "on" method caller completes. + */ +ServerRequest.prototype.on = function on(ev, fn) { + Server.prototype.on.call(this, ev, fn); + + if (ev === "data") { + process.nextTick(function () { + if (this.server.buffer.length !== 0) { + this.emit("data", this.server.buffer); + } + + }.bind(this)); + } +}; + +ServerRequest.prototype.addListener = ServerRequest.prototype.on; + function Server(requestListener) { EventEmitter.call(this); @@ -321,22 +343,20 @@ Server.prototype.listen = function () { }; Server.prototype.run_events = function (server, req, res) { + req.server = server; + res.server = server; + req.res = res; + res.req = req; + + server.buffer = server.unit._read(req.socket.req_pointer); + /* Important!!! setImmediate starts the next iteration in Node.js loop. */ setImmediate(function () { server.emit("request", req, res); - Promise.resolve().then(() => { - let buf = server.unit._read(req.socket.req_pointer); - - if (buf.length != 0) { - req.emit("data", buf); - } - - req.emit("end"); - }); - Promise.resolve().then(() => { req.emit("finish"); + req.emit("end"); if (res.finished) { unit_lib.unit_response_end(res); -- cgit