|
|
@@ -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); |