lib/network.js   A
last analyzed

Complexity

Total Complexity 34
Complexity/F 2.13

Size

Lines of Code 145
Function Count 16

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 34
eloc 93
mnd 18
bc 18
fnc 16
dl 0
loc 145
rs 9.68
bpm 1.125
cpm 2.125
noi 0
c 0
b 0
f 0
1
var args = require('./args.js');
2
var log = require('./logger.js').get();
3
4
var IP = null;
5
var machine = null;
6
var request = null;
7
8
var get_protocol = function() {
9
	return 'http' + (args.https && 's' || '') + '://';
10
};
11
12
var get_req = function(req, host) {
13
	return new Promise(function(resolve) {
14
		return request({
15
			method: req.method,
16
			url: host + req.originalUrl,
17
			headers: {
18
				'docker-server': 'force',
19
				'content-type': 'application/json',
20
				'authorization': req.get('Authorization')
21
			},
22
			body: req.method !== 'HEAD' && req.body && JSON.stringify(req.body) || undefined
23
		}, function (err, res, body) {
24
			log.debug('request:' + host + '::' + err + ' (' + (typeof body) + ') ' + JSON.stringify(body));
25
			if (err) {
26
				log.error('err:' + host + '::' + err);
27
				return resolve({'body': [err], 'host': host});
28
			}
29
			
30
			try {
31
				return resolve({'body': typeof body === 'string' && JSON.parse(body) || body, 'host': host});
32
			} catch(e) {
33
				if (body.startsWith('error')) {
34
					body = {'error': body};
35
				} else {
36
					log.error('request:' + host + '::' + err + ' (' + (typeof body) + ') ' + JSON.stringify(body));
37
				}
38
				
39
				return resolve({'body': [body], 'host': host});
40
			}
41
		});
42
	});
43
};
44
45
var handle_cluster_request = function(req, res, next) {
46
	return function(ip) {
47
		if (ip === IP) {
48
			next();
49
		} else {
50
			get_req(req, ip).then(function(ip_obj) {
51
				res.send(ip_obj.body || null);
52
			});
53
		}
54
	};
55
};
56
57
var handle_cluster = function(req, res, next) {
58
	if (req.method === 'PUT') {
59
		machine.next(IP).then(handle_cluster_request(req, res, next));
60
	} else if (~['GET', 'DELETE', 'HEAD', 'POST'].indexOf(req.method)) {
61
		machine.all(IP).then(function(ips) {
62
			var promises = [];
63
			for (var i in ips) {
64
				if (ips.hasOwnProperty(i)) {
65
					promises.push(get_req(req, ips[i].host));
66
				}
67
			}
68
			
69
			return Promise.all(promises).then(function(responses) {
70
				var response = [];
71
				for (var i = 0; i < responses.length; ++i) {
72
					// Add the host to each result for more clearance for the client.
73
					if (responses[i].body.length) {
74
						for (var j in responses[i].body) {
75
							if (responses[i].body.hasOwnProperty(j)) {
76
								responses[i].body.host = responses[i].host;
77
							}
78
						}
79
					} else {
80
						responses[i].body.host = responses[i].host;
81
					}
82
					response = response.concat(responses[i].body);
83
				}
84
				
85
				res.send(req.method !== 'HEAD' && response || undefined);
86
			});
87
		});
88
	} else {
89
		res.sendStatus(400);
90
	}
91
};
92
93
94
module.exports = {
95
	'get_protocol': get_protocol,
96
	'check': function(token) {
97
		return function (req, res, next) {
98
			if (req.get('Authorization') === token) {
99
				next();
100
			} else {
101
				res.sendStatus(401);
102
			}
103
		};
104
	},
105
	'protocol': function(app) {
106
		if (args.https) {
107
			const fs = require('fs');
108
			
109
			if (fs.existsSync('/certs/privkey.pem') && fs.existsSync('/certs/cert.pem')) {
110
				try {
111
					return require('https').createServer({
112
						key: fs.readFileSync('/certs/privkey.pem', 'utf8'),
113
						cert: fs.readFileSync('/certs/cert.pem', 'utf8'),
114
						ca: fs.existsSync('/certs/chain.pem') && fs.readFileSync('/certs/chain.pem', 'utf8') || undefined
115
					}, app);
116
				} catch (e) {
117
					log.error('Could not start secure server: ' + e);
118
					return require('http').createServer(app);
119
				}
120
			}
121
		}
122
		
123
		return require('http').createServer(app);
124
	},
125
	'balance': function(port) {
126
		if (args.cluster) {
127
			// This runs only once
128
			IP = get_protocol() + require('ip').address() + ':' + port;
129
			machine = require('./machine.js');
130
			request = require('request');
131
			
132
			machine.cpu(IP);
133
			setInterval(function() { machine.cpu(IP); }, args.refresh_rate);
134
		}
135
		
136
		return function (req, res, next) {
137
			// This runs every request
138
			if (args.cluster && req.get('docker-server') !== 'force') {
139
				handle_cluster(req, res, next);
140
			} else {
141
				next();
142
			}
143
		};
144
	}
145
};