diff --git a/lib/eventsource.js b/lib/eventsource.js index b90a6c5..93628b4 100644 --- a/lib/eventsource.js +++ b/lib/eventsource.js @@ -42,7 +42,7 @@ function EventSource(url) { var buf = ''; res.on('data', function (chunk) { buf = buf + chunk; - var messages = buf.match(/(.|\r?\n)*\r?\n\r?\n/) + var messages = buf.match(/(.|\r\n|\n|\r)*(\n\n|\r\r|\r\n\r\n)/); if (!messages) return; messages = messages[0]; buf = buf.slice(messages.length); diff --git a/lib/eventstream.jison b/lib/eventstream.jison index 6f838de..e33f070 100644 --- a/lib/eventstream.jison +++ b/lib/eventstream.jison @@ -3,7 +3,8 @@ ^\uFEFF /* skip leading byte order mark */ \u0020 return 'space'; -\u000D?\u000A return 'eol'; +\u000D return 'cr'; +\u000A return 'lf'; ":" return 'colon'; [\u0000-\u0009\u000B-\u000C\u000E-\u0019\u0021-\u0039\u003B-\u10FFFF] return 'char'; <> return 'EOF'; @@ -95,3 +96,8 @@ name-char | space ; +eol + : cr lf + | cr + | lf + ; diff --git a/lib/eventstream.js b/lib/eventstream.js index d5e45f5..e5a752e 100644 --- a/lib/eventstream.js +++ b/lib/eventstream.js @@ -2,9 +2,9 @@ var eventstream = (function(){ var parser = {trace: function trace() { }, yy: {}, -symbols_: {"error":2,"expressions":3,"events":4,"EOF":5,"event":6,"eol":7,"row":8,"field":9,"comment":10,"colon":11,"any-string":12,"name-string":13,"any-char":14,"name-char":15,"char":16,"space":17,"$accept":0,"$end":1}, -terminals_: {2:"error",5:"EOF",7:"eol",11:"colon",16:"char",17:"space"}, -productions_: [0,[3,2],[4,3],[4,2],[6,2],[6,1],[8,1],[8,1],[10,3],[10,2],[9,4],[9,3],[9,2],[12,1],[12,2],[13,1],[13,2],[14,1],[14,1],[14,1],[15,1],[15,1]], +symbols_: {"error":2,"expressions":3,"events":4,"EOF":5,"event":6,"eol":7,"row":8,"field":9,"comment":10,"colon":11,"any-string":12,"name-string":13,"any-char":14,"name-char":15,"char":16,"space":17,"cr":18,"lf":19,"$accept":0,"$end":1}, +terminals_: {2:"error",5:"EOF",11:"colon",16:"char",17:"space",18:"cr",19:"lf"}, +productions_: [0,[3,2],[4,3],[4,2],[6,2],[6,1],[8,1],[8,1],[10,3],[10,2],[9,4],[9,3],[9,2],[12,1],[12,2],[13,1],[13,2],[14,1],[14,1],[14,1],[15,1],[15,1],[7,2],[7,1],[7,1]], performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { var $0 = $$.length - 1; @@ -52,7 +52,7 @@ case 16: this.$ = $$[$0-1] + $$[$0]; break; } }, -table: [{3:1,4:2,6:3,8:4,9:5,10:6,11:[1,8],13:7,15:9,16:[1,10],17:[1,11]},{1:[3]},{5:[1,12],6:13,8:4,9:5,10:6,11:[1,8],13:7,15:9,16:[1,10],17:[1,11]},{7:[1,14],8:15,9:5,10:6,11:[1,8],13:7,15:9,16:[1,10],17:[1,11]},{7:[2,5],11:[2,5],16:[2,5],17:[2,5]},{7:[2,6],11:[2,6],16:[2,6],17:[2,6]},{7:[2,7],11:[2,7],16:[2,7],17:[2,7]},{7:[1,17],11:[1,16],15:18,16:[1,10],17:[1,11]},{7:[1,20],11:[1,22],12:19,14:21,16:[1,23],17:[1,24]},{7:[2,15],11:[2,15],16:[2,15],17:[2,15]},{7:[2,20],11:[2,20],16:[2,20],17:[2,20]},{7:[2,21],11:[2,21],16:[2,21],17:[2,21]},{1:[2,1]},{7:[1,25],8:15,9:5,10:6,11:[1,8],13:7,15:9,16:[1,10],17:[1,11]},{5:[2,3],11:[2,3],16:[2,3],17:[2,3]},{7:[2,4],11:[2,4],16:[2,4],17:[2,4]},{7:[1,27],11:[1,22],12:26,14:21,16:[1,23],17:[1,24]},{7:[2,12],11:[2,12],16:[2,12],17:[2,12]},{7:[2,16],11:[2,16],16:[2,16],17:[2,16]},{7:[1,28],11:[1,22],14:29,16:[1,23],17:[1,24]},{7:[2,9],11:[2,9],16:[2,9],17:[2,9]},{7:[2,13],11:[2,13],16:[2,13],17:[2,13]},{7:[2,17],11:[2,17],16:[2,17],17:[2,17]},{7:[2,18],11:[2,18],16:[2,18],17:[2,18]},{7:[2,19],11:[2,19],16:[2,19],17:[2,19]},{5:[2,2],11:[2,2],16:[2,2],17:[2,2]},{7:[1,30],11:[1,22],14:29,16:[1,23],17:[1,24]},{7:[2,11],11:[2,11],16:[2,11],17:[2,11]},{7:[2,8],11:[2,8],16:[2,8],17:[2,8]},{7:[2,14],11:[2,14],16:[2,14],17:[2,14]},{7:[2,10],11:[2,10],16:[2,10],17:[2,10]}], +table: [{3:1,4:2,6:3,8:4,9:5,10:6,11:[1,8],13:7,15:9,16:[1,10],17:[1,11]},{1:[3]},{5:[1,12],6:13,8:4,9:5,10:6,11:[1,8],13:7,15:9,16:[1,10],17:[1,11]},{7:14,8:15,9:5,10:6,11:[1,8],13:7,15:9,16:[1,10],17:[1,11],18:[1,16],19:[1,17]},{11:[2,5],16:[2,5],17:[2,5],18:[2,5],19:[2,5]},{11:[2,6],16:[2,6],17:[2,6],18:[2,6],19:[2,6]},{11:[2,7],16:[2,7],17:[2,7],18:[2,7],19:[2,7]},{7:19,11:[1,18],15:20,16:[1,10],17:[1,11],18:[1,16],19:[1,17]},{7:22,11:[1,24],12:21,14:23,16:[1,25],17:[1,26],18:[1,16],19:[1,17]},{11:[2,15],16:[2,15],17:[2,15],18:[2,15],19:[2,15]},{11:[2,20],16:[2,20],17:[2,20],18:[2,20],19:[2,20]},{11:[2,21],16:[2,21],17:[2,21],18:[2,21],19:[2,21]},{1:[2,1]},{7:27,8:15,9:5,10:6,11:[1,8],13:7,15:9,16:[1,10],17:[1,11],18:[1,16],19:[1,17]},{5:[2,3],11:[2,3],16:[2,3],17:[2,3]},{11:[2,4],16:[2,4],17:[2,4],18:[2,4],19:[2,4]},{5:[2,23],11:[2,23],16:[2,23],17:[2,23],18:[2,23],19:[1,28]},{5:[2,24],11:[2,24],16:[2,24],17:[2,24],18:[2,24],19:[2,24]},{7:30,11:[1,24],12:29,14:23,16:[1,25],17:[1,26],18:[1,16],19:[1,17]},{11:[2,12],16:[2,12],17:[2,12],18:[2,12],19:[2,12]},{11:[2,16],16:[2,16],17:[2,16],18:[2,16],19:[2,16]},{7:31,11:[1,24],14:32,16:[1,25],17:[1,26],18:[1,16],19:[1,17]},{11:[2,9],16:[2,9],17:[2,9],18:[2,9],19:[2,9]},{11:[2,13],16:[2,13],17:[2,13],18:[2,13],19:[2,13]},{11:[2,17],16:[2,17],17:[2,17],18:[2,17],19:[2,17]},{11:[2,18],16:[2,18],17:[2,18],18:[2,18],19:[2,18]},{11:[2,19],16:[2,19],17:[2,19],18:[2,19],19:[2,19]},{5:[2,2],11:[2,2],16:[2,2],17:[2,2]},{5:[2,22],11:[2,22],16:[2,22],17:[2,22],18:[2,22],19:[2,22]},{7:33,11:[1,24],14:32,16:[1,25],17:[1,26],18:[1,16],19:[1,17]},{11:[2,11],16:[2,11],17:[2,11],18:[2,11],19:[2,11]},{11:[2,8],16:[2,8],17:[2,8],18:[2,8],19:[2,8]},{11:[2,14],16:[2,14],17:[2,14],18:[2,14],19:[2,14]},{11:[2,10],16:[2,10],17:[2,10],18:[2,10],19:[2,10]}], defaultActions: {12:[2,1]}, parseError: function parseError(str, hash) { throw new Error(str); @@ -376,20 +376,22 @@ case 0:/* skip leading byte order mark */ break; case 1:return 17; break; -case 2:return 7; +case 2:return 18; break; -case 3:return 11; +case 3:return 19; break; -case 4:return 16; +case 4:return 11; break; -case 5:return 5; +case 5:return 16; break; -case 6:return 'INVALID'; +case 6:return 5; +break; +case 7:return 'INVALID'; break; } }; -lexer.rules = [/^^\uFEFF/,/^\u0020/,/^\u000D?\u000A/,/^:/,/^[\u0000-\u0009\u000B-\u000C\u000E-\u0019\u0021-\u0039\u003B-\u10FFFF]/,/^$/,/^./]; -lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6],"inclusive":true}}; +lexer.rules = [/^^\uFEFF/,/^\u0020/,/^\u000D/,/^\u000A/,/^:/,/^[\u0000-\u0009\u000B-\u000C\u000E-\u0019\u0021-\u0039\u003B-\u10FFFF]/,/^$/,/^./]; +lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7],"inclusive":true}}; return lexer;})() parser.lexer = lexer; return parser; diff --git a/test/eventsource_test.js b/test/eventsource_test.js index 16c1df6..dc2fb2a 100644 --- a/test/eventsource_test.js +++ b/test/eventsource_test.js @@ -100,6 +100,44 @@ exports['Messages'] = { }); }, + 'accepts CRLF as separator': function(test) { + var chopped = "data: Aslak\r\n\r\ndata: Hellesøy\r\n\r\n".split(""); + createServer(chopped, function(close) { + var es = new EventSource('http://localhost:' + port); + es.onmessage = first; + + function first(m) { + test.equal("Aslak", m.data); + es.onmessage = second; + } + + function second(m) { + test.equal("Hellesøy", m.data); + es.close(); + close(test.done); + } + }); + }, + + 'accepts CR as separator': function(test) { + var chopped = "data: Aslak\r\rdata: Hellesøy\r\r".split(""); + createServer(chopped, function(close) { + var es = new EventSource('http://localhost:' + port); + es.onmessage = first; + + function first(m) { + test.equal("Aslak", m.data); + es.onmessage = second; + } + + function second(m) { + test.equal("Hellesøy", m.data); + es.close(); + close(test.done); + } + }); + }, + 'delivers message with explicit event': function(test) { createServer(["event: greeting\ndata: Hello\n\n"], function(close) { var es = new EventSource('http://localhost:' + port);