Skip to content

Commit

Permalink
Implement xml/plain event message handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Chad Engler authored and Chad Engler committed Oct 5, 2012
1 parent efec85d commit 8a46a14
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 9 deletions.
63 changes: 55 additions & 8 deletions lib/esl/parser.js
@@ -1,6 +1,7 @@
var esl = require('../esl'),
utile = require('utile'),
events = require('events');
events = require('events'),
xml2js = require('xml2js');

//liberal inspiration from: http://shimaore.github.com/esl/esl.html

Expand All @@ -23,8 +24,10 @@ var Parser = exports.Parser = function(socket) {
utile.inherits(Parser, events.EventEmitter);

Parser.prototype._onData = function(data) {
//if we have found a Content-Length header, parse as body
if(this.bodyLen > 0)
return this._parseBody(data);
//otherwise this is more headers
else
return this._parseHeaders(data);
};
Expand All @@ -33,13 +36,14 @@ Parser.prototype._onEnd = function() {
};

Parser.prototype._parseHeaders = function(data) {
//buffer this header data
this.buffer += data;

//get end of header marker
var headEnd = this.buffer.indexOf('\n\n'),
headText;

//if the headers haven't ended yet, keep soaking it up
//if the headers haven't ended yet, keep buffering
if(headEnd < 0)
return;

Expand All @@ -53,7 +57,9 @@ Parser.prototype._parseHeaders = function(data) {
this.headers = this._parseHeaderText(headText);

if(this.headers['Content-Length']) {
//set bodyLen so next data event with process as body
this.bodyLen = this.headers['Content-Length'];

//continue processing the buffer as body
this._parseBody('');
}
Expand All @@ -67,9 +73,10 @@ Parser.prototype._parseHeaders = function(data) {
};

Parser.prototype._parseBody = function(data) {
//buffer this body data
this.buffer += data;

//haven't got entire buffer yet
//haven't buffered the entire body yet
if(this.buffer.length < this.bodyLen)
return;

Expand Down Expand Up @@ -98,13 +105,51 @@ Parser.prototype._parseHeaderText = function(txt) {
return headers;
};

Parser.prototype._parseXmlHeaderText = function(txt) {
Parser.prototype._parseXmlBody = function(txt, cb) {
//in the form:
//<event>
// <headers>...</headers>
// <Content-Length>4</Content-Length> [optional]
// <body>...</body> [optional]
//</event>
var parser = new xml2js.Parser({ explicitArray: false, explicitRoot: false }),
self = this, headers = {};

//parsing the xml is synchronous, despite the callback
parser.parseString(txt, function(err, data) {
if(err) {
self.emit('error', err);
}
//do a little bit of massaging to get it into the same format
//as what a JSON message looks like
headers = data.headers;

if(data['Content-Length']) {
headers['Content-Length'] = data['Content-Length'];
headers._body = data.body;
}
});

return headers;
};

Parser.prototype._parsePlainBody = function(txt) {
//if the body is event-plain then it is just a bunch of key/value pairs
var headerEnd = txt.indexOf('\n\n'),
headers = this._parseHeaderText(txt.substring(0, headerEnd));

if(headers['Content-Length']) {
var len = parseInt(headers['Content-Length'], 10);

//do count with substr instead of index with substring this time
headers._body = txt.substr(headerEnd + 2, len);
}

return headers;
};

Parser.prototype._parseEvent = function(headers, body) {
var event = new esl.Event(headers, body),
data;
var event, data;

switch(headers['Content-Type']) {
//parse body as JSON event data
Expand All @@ -115,17 +160,19 @@ Parser.prototype._parseEvent = function(headers, body) {

//parse body as PLAIN event data
case 'text/event-plain':
data = this._parseHeaderText(body);
data = this._parsePlainBody(body);
break;

//parse body as XML event data
case 'text/event-xml':
data = this._parseXmlHeaderText(body);
data = this._parseXmlBody(body);
break;
}

if(data)
event = new esl.Event(data);
else
event = new esl.Event(headers, body);

this.emit('esl::event', event, headers, body);
};
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -13,7 +13,8 @@
"main": "lib/esl.js",
"dependencies": {
"utile": "0.1.x",
"eventemitter2": "0.4.x"
"eventemitter2": "0.4.x",
"xml2js": "0.2.x"
},
"devDependencies": {
"vows": "0.6.x"
Expand Down

0 comments on commit 8a46a14

Please sign in to comment.