Skip to content

Instantly share code, notes, and snippets.

@AlexF4Dev
Forked from miensol/net-proxy.js
Created January 12, 2025 23:19
Show Gist options
  • Save AlexF4Dev/651a61119dcece73a79ddfa04fbdfdff to your computer and use it in GitHub Desktop.
Save AlexF4Dev/651a61119dcece73a79ddfa04fbdfdff to your computer and use it in GitHub Desktop.
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);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment