diff --git a/lib/http.js b/lib/http.js index 28e3e3e2498..68b4fa2bbf4 100644 --- a/lib/http.js +++ b/lib/http.js @@ -76,7 +76,13 @@ var parsers = new FreeList('parsers', 1000, function () { parser.incoming.statusCode = info.statusCode; } - parser.onIncoming(parser.incoming, info.shouldKeepAlive); + parser.incoming.upgrade = info.upgrade; + + if (!info.upgrade) { + // For upgraded connections, we'll emit this after parser.execute + // so that we can capture the first part of the new protocol + parser.onIncoming(parser.incoming, info.shouldKeepAlive); + } }; parser.onBody = function (b, start, len) { @@ -91,7 +97,10 @@ var parsers = new FreeList('parsers', 1000, function () { }; parser.onMessageComplete = function () { - parser.incoming.emit("end"); + if (!parser.incoming.upgrade) { + // For upgraded connections, also emit this after parser.execute + parser.incoming.emit("end"); + } }; return parser; @@ -512,7 +521,16 @@ function connectionListener (socket) { parser.socket = socket; socket.ondata = function (d, start, end) { - parser.execute(d, start, end - start); + var bytesParsed = parser.execute(d, start, end - start); + if (parser.incoming && parser.incoming.upgrade) { + var upgradeHead = d.slice(start + bytesParsed, end - start); + parser.incoming.upgradeHead = upgradeHead; + socket.ondata = null; + socket.onend = null; + + self.emit('request', parser.incoming, null); + parser.incoming.emit('end'); + } }; socket.onend = function () { @@ -579,8 +597,16 @@ function Client ( ) { requests.push(req); }; - this.ondata = function (d, start, end) { - parser.execute(d, start, end - start); + self.ondata = function (d, start, end) { + var bytesParsed = parser.execute(d, start, end - start); + if (parser.incoming && parser.incoming.upgrade) { + var upgradeHead = d.slice(start + bytesParsed, end - start); + parser.incoming.upgradeHead = upgradeHead; + currentRequest.emit("response", parser.incoming); + parser.incoming.emit('end'); + self.ondata = null; + self.onend = null + } }; self.addListener("connect", function () { @@ -590,12 +616,12 @@ function Client ( ) { currentRequest.flush(); }); - self.addListener("end", function () { + self.onend = function () { parser.finish(); debug("self got end closing. readyState = " + self.readyState); self.end(); - }); + }; self.addListener("close", function (e) { if (e) { diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index e5dbed38f15..c7e69fc1323 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -61,6 +61,7 @@ static Persistent http_version_sym; static Persistent version_major_sym; static Persistent version_minor_sym; static Persistent should_keep_alive_sym; +static Persistent upgrade_sym; static struct http_parser_settings settings; @@ -165,6 +166,8 @@ class Parser : public ObjectWrap { message_info->Set(should_keep_alive_sym, http_should_keep_alive(p) ? True() : False()); + message_info->Set(upgrade_sym, p->upgrade ? True() : False()); + Local argv[1] = { message_info }; Local ret = cb->Call(parser->handle_, 1, argv); @@ -243,7 +246,7 @@ class Parser : public ObjectWrap { Local nparsed_obj = Integer::New(nparsed); // If there was a parse error in one of the callbacks // TODO What if there is an error on EOF? - if (nparsed != len) { + if (!parser->parser_.upgrade && nparsed != len) { Local e = Exception::Error(String::New("Parse Error")); Local obj = e->ToObject(); obj->Set(String::NewSymbol("bytesParsed"), nparsed_obj); @@ -345,6 +348,7 @@ void InitHttpParser(Handle target) { version_major_sym = NODE_PSYMBOL("versionMajor"); version_minor_sym = NODE_PSYMBOL("versionMinor"); should_keep_alive_sym = NODE_PSYMBOL("shouldKeepAlive"); + upgrade_sym = NODE_PSYMBOL("upgrade"); settings.on_message_begin = Parser::on_message_begin; settings.on_path = Parser::on_path;