-
Notifications
You must be signed in to change notification settings - Fork 1
/
danby.js
executable file
·131 lines (109 loc) · 3.82 KB
/
danby.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env node
var yargs = require('yargs')
.option('port', { describe: 'http port', demandOption:true})
.option('cfg', { describe: 'path to json config file'})
.option('cert', { describe: 'path to cert file'})
.option('key', { describe: 'path to private key for ssl/tls'})
.option('webroot', { describe: 'path to webroot, defaults to $PWD'})
.option('debug', { describe: 'debug output to console'});
var argv = yargs.argv;
var express = require('express');
var https = require('https');
var proxy = require('express-http-proxy');
var fs = require('fs')
var protobuf = require('protobufjs');
var api = require('./template-parser');
var app = express();
var expressWs = require('express-ws')(app);
var wsProto = typeof(argv.cert)=='undefined' ? "ws": "wss";
var grpc = require('grpc');
var toml = require('toml');
var services = {};
var apiText="";
var cfgData = null;
function getSvcRemote(svcName) {
return "services['" + svcName + "'].remote." + svcName;
}
function getSvcConnect(svcName) {
return "services['" + svcName + "'].grpc";
}
async function main() {
if (typeof(argv.cfg)!=='undefined') {
cfgData = toml.parse(fs.readFileSync(argv.cfg,'utf8'));
var servers = [];
Object.keys(cfgData["server"]).forEach((name) => {
servers.push(cfgData["server"][name]);
});
for (let item of servers) {
if (item.service) {
let root = await protobuf.load(item.proto);
const apiData = api(root,item.service, wsProto);
var generatedApi = apiData["output"];
var methodNames = apiData["methods"];
var proto = grpc.load(item.proto);
var stub=null;
eval("stub = proto." + item.pkg);
var service = { cfg:item, api:generatedApi,methods:methodNames,remote:stub, grpc:item.grpc};
services[item.service] = service;
apiText+=generatedApi;
}
}
}
app.use(require('helmet')());
if (typeof(argv.webroot)=='undefined')
app.use('/', express.static("."));
else
app.use('/', express.static(argv.webroot));
if (cfgData !==null) {
Object.keys(cfgData["proxy"]).forEach((name) => {
var fromRoute = cfgData["proxy"][name]["from"];
var dest = cfgData["proxy"][name]["to"];
if (fromRoute && dest)
app.use(fromRoute, proxy(dest));
});
}
app.get('/grpc-api', function(req, res, next) {
res.setHeader("Content-Type", "application/javascript");
res.send(apiText);
res.end();
});
app.ws('/grpc-ws', function(ws, req) {
ws.on('message', function(msg) {
function respond(data) {
var str = JSON.stringify(data);
if (typeof(argv.debug)!=='undefined' && argv.debug==='true')
console.log("S:" + str);
ws.send(str);
ws.close();
};
//Input filtering by relying on Node.js's builtin json parsing automata to reject invalid json
var obj = JSON.parse(msg);
var metadata = new grpc.Metadata();
if (services[obj["service"]].methods.includes(obj["method"]) && typeof(obj["payload"]==='object')) {
var client;
if (typeof(obj["metadata"])!=='undefined') {
Object.keys(obj["metadata"]).forEach((name,idx) => {
metadata.set(name, obj["metadata"][name]);
});
}
var cmd = "client = new " + getSvcRemote(obj["service"]) + "(" + getSvcConnect(obj["service"]) + ", grpc.credentials.createInsecure())";
if (typeof(argv.debug)!=='undefined' && argv.debug==='true')
console.log("C:" + cmd);
eval(cmd);
var call = "client." + obj["method"] + "(" + JSON.stringify(obj["payload"]) + ", metadata , function (err,response) { respond(response); });";
if (typeof(argv.debug)!=='undefined' && argv.debug==='true')
console.log("C:" + call);
eval(call);
}
});
});
app.listen(argv.port);
if (typeof(argv.cert)!=='undefined' && typeof(argv.key)!=='undefined') {
var options = {
cert : fs.readFileSync(argv.cert),
key : fs.readFileSync(argv.key)
};
https.createServer(options,app).listen(443);
}
}
main();