diff --git a/README.md b/README.md index d493a5c..5009dbd 100644 --- a/README.md +++ b/README.md @@ -5,5 +5,6 @@ INSTALLATION cd ws_rev_proxy npm install node run server & - node run client kpz-1 <forward-to-host> <forward-to-port> & # forward-to-* points to a server to forward http to - curl localhost:8080/api/kpz-1<path> # path is the path to get from <forward-to-host> + 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> diff --git a/client/index.js b/client/index.js index 990dfe9..bb3cbc0 100644 --- a/client/index.js +++ b/client/index.js @@ -1,28 +1,37 @@ 'use strict'; //-- vim: ft=javascript tabstop=2 softtabstop=2 expandtab shiftwidth=2 +const path = require('path'); const http = require('http'); const WebSocket = require('ws'); -const ws_ = new WebSocket(`ws://localhost:8080/ws/pill/${process.argv[2]}`); const WsJsonProtocol = require('../lib/ws-json'); + +const client_key = process.argv[2]; +const server_host_port = process.argv[3]; +const forward_base_uri = process.argv[4]; + +if (client_key === undefined) { + throw new Error("Missing client key."); +} + +const ws_ = new WebSocket(`ws://${server_host_port}/ws/${client_key}`); const ws = new WsJsonProtocol(ws_); -const forward_host = process.argv[3]; -const forward_port = process.argv[4]; class RequestForwarder extends Object { - constructor(ws, host, port) { + constructor(ws, forward_base_uri) { super(); - if (!host || !port) throw new Error("Host and port are required arguments."); - this._forward_host = host; - this._forward_port = port; + if (!forward_base_uri) throw new Error("Missing the base uri to forward to."); + let parsed_uri = new URL(forward_base_uri); + if (parsed_uri.search) throw new Error("Search path is not implemented yet for forward base uri."); + if (!parsed_uri.protocol.match(/^https?:$/i)) throw new Error(`Only HTTP(s) protocol is implemented for forward base uri (got ${parsed_uri.protocol}).`); + this._forward_base_uri = parsed_uri; this._ws = ws; } fire_request(message, ) { const ireq = message.request; + 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); const req_params = { - host: this._forward_host, - port: this._forward_port, - path: ireq.url, method: ireq.method, headers: ireq.headers, } @@ -37,7 +46,7 @@ class RequestForwarder extends Object { }) } } - const req = http.request(req_params, function handleResponse(res) { + const req = http.request(oreq_uri.toString(), req_params, function handleResponse(res) { res.setEncoding('utf8'); sender('headers')({ statusCode: res.statusCode, @@ -48,6 +57,7 @@ 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); @@ -57,8 +67,8 @@ class RequestForwarder extends Object { } _send(data) { - console.log(`Sending ${message}`) - this._ws.send(message); + console.log(`Sending ${JSON.stringify(data)}`) + this._ws.send(data); } on_message(message) { @@ -69,7 +79,7 @@ class RequestForwarder extends Object { ws.on('open', function open() { - const request_forwarder = new RequestForwarder(ws, forward_host, forward_port); + const request_forwarder = new RequestForwarder(ws, forward_base_uri); console.log("Client connection openned."); ws.send({data:"Hallo."}); diff --git a/lib/ws-json.js b/lib/ws-json.js index 517c71e..ae56fb7 100644 --- a/lib/ws-json.js +++ b/lib/ws-json.js @@ -32,12 +32,14 @@ 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 { - let decodedMessage = decode_(message); + decodedMessage = decode_(message); } catch(err) { console.error(err); } + console.log(`decoded message ${JSON.stringify(decodedMessage, undefined, 3)}`); if (decodedMessage !== undefined) { callback(decodedMessage); } diff --git a/server/api.js b/server/api.js index ee4db97..9f0daad 100644 --- a/server/api.js +++ b/server/api.js @@ -85,6 +85,7 @@ class Api extends Object { 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}`); websocket_client.send(JSON.stringify({ channel: channel, id: req_id, diff --git a/server/authenticator.js b/server/authenticator.js index 288ee69..e385518 100644 --- a/server/authenticator.js +++ b/server/authenticator.js @@ -10,7 +10,7 @@ class KeyAuthenticator extends Object { authenticate(request, callback) { console.log(`Authenticating request ${request} on ${request.url}.`); - const match = /^\/ws\/pill\/(?<client_key>.*)$/.exec(request.url); + const match = /^\/ws\/(?<client_key>.*)$/.exec(request.url); if (! match) return callback(new Error("Unknown url.")); if (this.allowed_keys.has(match.groups.client_key)) { console.log(`Key ${match.groups.client_key} accepted`); @@ -23,6 +23,7 @@ class KeyAuthenticator extends Object { onConnected (ws, client) { this._clients_by_id[client.key] = ws; + ws.id = client.key; } clientFromId (id) { diff --git a/server/index.js b/server/index.js index 2fd0676..93ce536 100644 --- a/server/index.js +++ b/server/index.js @@ -6,7 +6,7 @@ const WebSocket = require('ws'); const Api = require('./api'); const KeyAuthenticator = require('./authenticator'); const authenticator = new KeyAuthenticator(['kpz-1', 'kpz-2', 'kpz-3']); -const server = http.createServer( +let server = http.createServer( new Api( '/api', authenticator.clientFromId.bind(authenticator) @@ -15,6 +15,9 @@ const server = http.createServer( const wss = new WebSocket.Server({ noServer: true }); +let server_port = process.argv[2]; + +if (! server_port) server_port=8000; /* * @authenticator ... function (request, callback) which calls callback(err, client). * `err` is empty on success and client which should be an object with `key` property. @@ -42,8 +45,9 @@ function createServer(authenticator) { wss.handleUpgrade(request, socket, head, function done(ws) { console.log("Emitting ws connection"); + ws.send(JSON.stringify({"data": "ping"})); authenticator.onConnected(ws, client); - ws.client = client; + ws.client_object = client; wss.emit('connection', ws, request, client); }); }); @@ -51,5 +55,16 @@ function createServer(authenticator) { return server; } -createServer(authenticator) - .listen(8080); +server = createServer(authenticator) +server.on("listening", function onListening() { + let addr = server.address(); + console.log(` + Listening on ${addr.address}:${addr.port}. + To connect clients run: + + node client <client-key> <server-host>:${addr.port} <uri-to-redirect-to> + `); + +}); +server.listen(server_port); +