Created
March 23, 2014 17:37
-
-
Save miensol/9726643 to your computer and use it in GitHub Desktop.
Revisions
-
miensol created this gist
Mar 23, 2014 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,118 @@ var net = require('net'), http = require('http'), Writable = require('stream').Writable, parsers = http.parsers, HTTPParser = process.binding('http_parser').HTTPParser, util = require('util'), EventEmitter = require('events').EventEmitter; function freeParser(parser, req) { if (parser) { parser._headers = []; parser.onIncoming = null; if (parser.socket) { parser.socket.onend = null; parser.socket.ondata = null; parser.socket.parser = null; } parser.socket = null; parser.incoming = null; parsers.free(parser); parser = null; } if (req) { req.parser = null; } } var HttpParsingStream = function (options) { Writable.call(this, {}); var socket = options.socket; var parser = parsers.alloc(); var streamChunks = []; var that = this; parser.reinitialize(options.parserMode); parser.socket = socket; socket.parser = parser; parser.onIncoming = function (request) { that.emit('headers', request); request.on('data', function () { //we either have to call resume or attach on data handler to get end event... // console.log(options.name + '.data', arguments); }); request.on('end', function () { that.emit('end'); freeParser(parser, request); }); }; socket.on('close', function () { that.emit('socket.close'); }); this._write = function (chunk, encoding, callback) { streamChunks.push({ chunk: chunk, encoding: encoding }); parser.execute(chunk, 0, chunk.length); callback && callback(); }; this.writeCurrentChunks = function (writableStream) { streamChunks.forEach(function (chunkObj) { console.log(chunkObj.chunk.toString('ascii')); writableStream.write(chunkObj.chunk, chunkObj.encoding); }); }; }; HttpParsingStream.createForRequest = function (socket) { return new HttpParsingStream({ socket: socket, parserMode: HTTPParser.REQUEST, name: 'request' }); }; HttpParsingStream.createForResponse = function (socket) { return new HttpParsingStream({ socket: socket, parserMode: HTTPParser.RESPONSE, name: 'response' }); }; util.inherits(HttpParsingStream, Writable); net.createServer(function (socketRequest) { var requestParser = HttpParsingStream.createForRequest(socketRequest); requestParser.on('headers', function (req) { console.log('request.headers'); //pause the request until we setup necessary plumbing req.pause(); var hostNameHeader = req.headers.host, hostAndPort = hostNameHeader.split(':'), host = hostAndPort[0], port = parseInt(hostAndPort[1]) || 80; var srvSocket = net.connect(port, host, function () { var responseParser = HttpParsingStream.createForResponse(srvSocket); responseParser.on('headers', function () { console.log('response.headers'); }); responseParser.on('end', function () { console.log('response.end'); }); srvSocket.pipe(responseParser); srvSocket.pipe(socketRequest); requestParser.writeCurrentChunks(srvSocket); socketRequest.pipe(srvSocket); req.resume(); }); }); requestParser.on('end', function () { console.log('request.end'); }); socketRequest.pipe(requestParser); }).listen(9000);