Skip to content

Commit

Permalink
fixed client key not release when connection closes, wrong handling of
Browse files Browse the repository at this point in the history
uri with search parameters, better logging
  • Loading branch information
Robin Gottfried committed Feb 18, 2020
1 parent 159225e commit 996428f
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 34 deletions.
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@

INSTALLATION
----

git clone ws_rev_proxy
cd ws_rev_proxy
# install node and npm
sudo apt install nodejs npm # it's roughly 50MB :(

# clone the repository
git clone https://github.com/czervenka/ws-proxy-poc.git
cd ws-proxy-poc

# install dependencies
npm install
node run server &

# run either
node run server <host>:<port> &
node run client <client-key> <server_host>:<server_port> <forward_to_base_uri> & # forward-to-* points to a server to forward http to
client_key=kpz-1
curl localhost:8080/api/$client_key # path is the path to get from <forward-to-host>


16 changes: 10 additions & 6 deletions client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,18 @@ class RequestForwarder extends Object {

fire_request(message, ) {
const ireq = message.request;
console.log(`< ${message.channel}: ${ireq.method} ${ireq.url}`);
let oreq_uri = new URL(this._forward_base_uri.toString()); // clone the original uri
oreq_uri.pathname = path.posix.join(oreq_uri.pathname, ireq.url);
oreq_uri.href = path.posix.join(oreq_uri.href, ireq.url);
const req_params = {
method: ireq.method,
headers: ireq.headers,
}
let _send = this._send.bind(this);
let sender = function sender(event_id) {
return function (data) {
if (event_id != 'data')
console.log(`<: ${message.channel}: ${event_id} ${ireq.method} ${oreq_uri.pathname}`);
_send({
channel: message.channel,
id: message.id,
Expand All @@ -46,8 +49,10 @@ class RequestForwarder extends Object {
})
}
}
console.log(` :> ${message.channel}: ${ireq.method} ${oreq_uri.pathname}`);
const req = http.request(oreq_uri.toString(), req_params, function handleResponse(res) {
res.setEncoding('utf8');
console.log(`<: ${message.channel}: ${res.statusCode} ${res.statusMessage} / ${ireq.method} ${oreq_uri.pathname}`);
sender('headers')({
statusCode: res.statusCode,
statusMessage: res.statusMessage,
Expand All @@ -57,17 +62,13 @@ class RequestForwarder extends Object {
res.on('end', sender('end'));
});
req.on('error', sender('error'));
console.log(`C > ${oreq_uri.toString()}`);
if (ireq.body) {
console.log(`Sending body ${ireq.body}`);
req.write(ireq.body);
}
req.end();
console.log(`End of request ${message.channel}`);
}

_send(data) {
console.log(`Sending ${JSON.stringify(data)}`)
this._ws.send(data);
}

Expand All @@ -84,7 +85,10 @@ ws.on('open', function open() {

ws.send({data:"Hallo."});
ws.on("message", function (message) {
console.log(`Got message\n------\n${message}\n------\n\n`);
request_forwarder.on_message(message);
});
ws.on("close", function onClose() {
console.log("Client connection closed.");
process.exit()
});
});
4 changes: 2 additions & 2 deletions lib/ws-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ class WsJsonProtocol extends Object {
on(eventName, callback) {
let decode_ = this._decode.bind(this);
let decoderCallback = function (message) {
console.log(`decoding message ${message}`);
let decodedMessage;
try {
decodedMessage = decode_(message);
} catch(err) {
console.error(err);
}
console.log(`decoded message ${JSON.stringify(decodedMessage, undefined, 3)}`);
if (decodedMessage !== undefined) {
callback(decodedMessage);
} else {
console.error(`! Could not decode message.`);
}
}
if (eventName == "message") {
Expand Down
42 changes: 20 additions & 22 deletions server/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const { HttpError, BadGateway } = require('./HttpError');

class Api extends Object {
constructor(path_prefix, get_client) {
console.log(`Constructor called with ${path_prefix} ${get_client}.`);
console.log(`Starting API with path prefix '${path_prefix}'.`);
super();
if (! path_prefix) {
path_prefix = '/';
Expand All @@ -30,7 +30,7 @@ class Api extends Object {


_request_handler(req, res) {
console.log(`api received ${req.method} ${req.url} ... matching against ${this._path_prefix}`);
console.log(`API < ${req.method} ${req.url} ... matching against ${this._path_prefix}`);
let path_info = this._parse_request_path(req);
if (!path_info || !path_info.id || ! path_info.resource) {
console.error(`Invalid url ${req.url}`);
Expand All @@ -53,26 +53,25 @@ class Api extends Object {
if (message.channel && message.channel == channel) {
switch(message.event) {
case 'headers':
console.log(message.event);
console.log(`<: ${channel}: ${message.data.statusCode} ${message.data.statusMessage} / ${message.event} ${req.method} ${req.url}`);
res.writeHead(message.data.statusCode, message.data.statusMessage, message.data.headers);
break;
case 'data':
console.log(message.event);
console.log(`<: ${channel}: data ${message.data.length}`);
res.write(message.data);
break;
case 'end':
console.log(message.event);
console.log(`<: ${channel}: end`);
res.end();
break;
case 'error':
console.log(message.event);
console.log(`<: ${channel}: error`);
res.writeHead(502, "Invalid gateway", {'content-type': 'application/json; charset=utf-8'});
res.write(JSON.stringify(message.data, undefined, 3));
res.end();
break;
default:
console.log(message.event);
console.error(`Unknown message type ${message.event}.`);
console.error(`<: ${channel}: Unknown message type ${message.event}.`);
websocket_client.close();
break;
}
Expand All @@ -83,9 +82,8 @@ class Api extends Object {
['method', 'headers']
.forEach((propertyName)=>request_data[propertyName]=req[propertyName]);
request_data.body = req.body;
console.log(request_data.body);
request_data.url = resource_path;
console.log(`Sending to ${client_id} req_id: ${req_id} to ${websocket_client.id}`);
console.log(` :> ${channel}: ${req.method} ${req.url}`);
websocket_client.send(JSON.stringify({
channel: channel,
id: req_id,
Expand All @@ -96,22 +94,22 @@ class Api extends Object {
get request_handler() {
return (function (req, res) {
req.body = '';
try {
// FIXME: this will not work for bigger request body. the stream needs to be forwarded
req.on('data', (chunk) => req.body += chunk);
req.on('end', () => {
this._request_handler(req, res);
try {
this._request_handler(req, res);
} catch(err) {
if (err instanceof HttpError) {
console.log(`! ${req.url} Error ${err}`);
res.writeHead(err.code, {'content-type': 'text/plain; charset=utf-8'});
res.write(err.toString());
res.end();
} else {
throw err;
}
}
});
} catch(err) {
if (err instanceof HttpError) {
console.log(`Error ${err}`);
res.writeHead(err.code, {'content-type': 'text/plain; charset=utf-8'});
res.write(err.toString());
res.end();
} else {
throw err;
}
}
}).bind(this);
}
}
Expand Down
4 changes: 4 additions & 0 deletions server/authenticator.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ class KeyAuthenticator extends Object {
ws.id = client.key;
}

onClose (ws, client) {
delete this._clients_by_id[client.key];
}

clientFromId (id) {
return this._clients_by_id[id];
}
Expand Down
6 changes: 5 additions & 1 deletion server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function createServer(authenticator) {
console.log('Client.ID: ' + client.id);
});
ws.on('message', function message(msg) {
console.log(`Received message ${msg} from client ${client.key}`);
// console.log(`Received message from client ${client.key}`);
});
});

Expand All @@ -50,6 +50,10 @@ function createServer(authenticator) {
wss.handleUpgrade(request, socket, head, function done(ws) {
console.log("Emitting ws connection");
ws.send(JSON.stringify({"data": "ping"}));
ws.on('close', function onClose() {
console.log(`Client ${client.key} closed connection.`);
authenticator.onClose(ws, client);
});
authenticator.onConnected(ws, client);
ws.client_object = client;
wss.emit('connection', ws, request, client);
Expand Down

0 comments on commit 996428f

Please sign in to comment.