I am trying to edit a node.js http stream before sending it to the parser. I have implemented the following code
//catch any connection event to this server
server.on('secureConnection', function (stream) {
//create a new buffer to hold what we are receiving in this stream
var receiveBuffer = new Buffer(0);
//store a link to the original ondata function so we can call it and restore it
originalOnDataFunction = stream.ondata;
//declare a new ondata function for this stream
stream.ondata = function (d, start, end) {
//record what we have received
receiveBuffer = Buffer.concat([receiveBuffer, d.slice(start, end)]);
//if what we have received is greater than 4 (i.e. we have at least got a GET request)
//then make changes
if (receiveBuffer.length >= 4) {
//reset the streams ondata function to the original
//this is all we want to edit for this connection
stream.ondata = originalOnDataFunction;
//if the first 11 characters of the buffer are 'MKCALENDAR ' then make a change
if (receiveBuffer.toString('ascii', 0, 11) === 'MKCALENDAR ') {
//I change this to MKCOL /MKCALENDAR<rest of buffer> as this will work with the node.js http parser
//and then I can check on the other side for a MKCOL method with /MKCALENDAR as the start of the url and
//know that it was a MKCALENDAR method
var rewrittenBuffer = Buffer.concat([new Buffer('MKCOL /MKCALENDAR', 'ascii'), receiveBuffer.slice(11)]);
//now call the original ondata function with this new buffer
stream.ondata.apply(this, [rewrittenBuffer, 0, rewrittenBuffer.length]);
} else {
//no change needed just call the original ondata function with this buffer
stream.ondata.apply(this, [receiveBuffer, 0, receiveBuffer.length]);
}
}
}
});
which I got from an answer here Overriding Node.js HTTP parser
The above code seems to work about 95% of the time. However, it keeps dropping requests that then just timeout. I cannot see how or where it is dropping them. Can anyone help.
Thanks,
Mark
Note the on secureConnection is coming from a node.js https.createServer( call
Are you sure you want
if (receiveBuffer.length >= 4)
If the first buffer is a partial MKCALENDAR with at least the first four bytes, the code above won't do the translation to MKCOL.
Jonathan the first packet in seems to be the all the headers so this line works fine. I did get it working and the problem seemed to be with the .apply statement not always working. The following works fine:
//catch any secure connection event to this server
server.on('secureConnection', function (stream) {
//create a new buffer to hold what we are receiving in this stream
var receiveBuffer = new Buffer(0);
//store a link to the original ondata function so we can call it and restore it
stream._ondataOld = stream.ondata;
stream.ondata = function(d,start,end){
receiveBuffer = Buffer.concat([receiveBuffer, d.slice(start, end)]);
//if what we have received is greater than 4 (i.e. we have at least got a GET request)
//then make changes
if (receiveBuffer.length >= 4) {
//reset the streams ondata function to the original
//this is all we want to edit for this connection
stream.ondata = stream._ondataOld;
//if the first 11 characters of the buffer are 'MKCALENDAR ' then make a change
if (receiveBuffer.toString('ascii', 0, 11) === 'MKCALENDAR ') {
//I change this to MKCOL /MKCALENDAR<rest of buffer> as this will work with the node.js http parser
//and then I can check on the other side for a MKCOL method with /MKCALENDAR as the start of the url and
//know that it was a MKCALENDAR method
//this facilitates MKCALENDAR calls on the CALDAV server
var rewrittenBuffer = Buffer.concat([new Buffer('MKCOL /MKCALENDAR', 'ascii'), receiveBuffer.slice(11)]);
//console.log(rewrittenBuffer.toString('ascii',0,rewrittenBuffer.length));
//console.log(rewrittenBuffer.toString('ascii'));
//now call the original ondata function with this new buffer
stream.ondata(rewrittenBuffer,0,rewrittenBuffer.length);
} else {
//no change needed just call the original ondata function with this buffer
stream.ondata(d,start,end);
}
} else {
stream.ondata(d,start,end);
}
}
});