Skip to content

Instantly share code, notes, and snippets.

@mdobson
Last active August 29, 2015 13:56
Show Gist options
  • Save mdobson/9239634 to your computer and use it in GitHub Desktop.
Save mdobson/9239634 to your computer and use it in GitHub Desktop.
Tunneling HTTP over WebSockets
var http = require('http');
var WebSocketServer = require('ws').Server;
var webSocket = null;
var server = http.createServer(function(req, res) {
var requestLine = [req.method.toUpperCase(), req.url, 'HTTP/' + req.httpVersion + '\r\n'].join(' ');
Object.keys(req.headers).forEach(function(header) {
requestLine += header + ': ' + req.headers[header] + '\r\n';
});
var buf = '';
if(webSocket) {
req.on('data', function(data) {
buf += data.toString();
});
req.on('end', function() {
if(buf.length) {
requestLine += '\r\n';
requestLine += buf;
requestLine += '\r\n\r\n';
} else {
requestLine += '\r\n\r\n';
}
webSocket.send(requestLine);
});
webSocket.once('message', function(data) {
var response = data.split('\r\n\r\n');
var headersNShit = response.shift().split('\r\n');
var body = response.join();
var statusLine = headersNShit.shift();
headersNShit.forEach(function(header) {
var headerPair = header.split(':');
res.setHeader(headerPair[0], headerPair[1].trim());
});
statusLine = statusLine.split(' ');
res.statusCode = statusLine[1];
res.end(body);
//req.socket.write(data);
});
}
});
var wss = new WebSocketServer({ server: server });
wss.on('connection', function(ws) {
webSocket = ws;
});
server.listen(3000);
var WebSocket = require('ws');
var FakeSocket = require('./fake_socket');
var http = require('http');
var argo = require('argo');
var resource = require('argo-resource');
var Hello = require('./hello_resource');
var ws = new WebSocket('ws://localhost:3000');
var app = argo()
.use(function(handle) {
handle('request', function(env, next) {
env.response.on('finish', function() {
ws.send(env.request.socket.data.toString());
});
//env.response.setHeader('Content-Length', env.request.url.length);
//env.response.body = env.request.url;
next(env);
});
})
.use(resource(Hello))
.build();
var server = http.createServer(app.run);
/*
var server = http.createServer(function(req, res) {
res.on('finish', function() {
ws.send(req.socket.data.toString());
});
res.setHeader('Content-Length', req.url.length);
res.end(req.url);
});
*/
ws.on('open', function() {
});
ws.on('message', function(data) {
var fake = new FakeSocket();
fake.write(data);
fake.on('readable', function() {
var data;
while (data = fake.read()) {
this.ondata(data, 0, data.length);
}
});
server.emit('connection', fake);
});
var stream = require('stream');
var util = require('util');
var FakeSocket = module.exports = function() {
this.data = [];
stream.Duplex.call(this);
};
util.inherits(FakeSocket, stream.Duplex);
FakeSocket.prototype.setTimeout = function() { };
FakeSocket.prototype.destroy = function() { };
FakeSocket.prototype._read = function(n) {
if (!this.data.length) {
return null;
}
var bytes = this.data.shift();
return this.unshift(bytes);
};
FakeSocket.prototype._write = function(chunk, encoding, cb) {
if (!chunk || chunk == 0) {
return cb();
}
this.data.push(chunk);
cb();
};
var Hello = module.exports = function() {};
Hello.prototype.init = function(config) {
config
.path('/test')
.consumes('application/json')
.get('/', this.hello)
.post('/', this.greet);
};
Hello.prototype.hello = function(env, next) {
env.response.statusCode = 200;
env.response.body = 'Hello world!';
next(env);
};
Hello.prototype.greet = function(env, next) {
env.request.getBody(function(err, body) {
if(err) {
console.log(err);
} else {
var b = JSON.parse(body.toString());
env.response.statusCode = 200;
env.response.body = 'Hello, ' + b.name + '!';
next(env);
}
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment