UNPKG

10.7 kBJavaScriptView Raw
1var path = require('path');
2var fs = require('fs');
3var eventStream = require('event-stream');
4var express = require('express');
5var request = require('request');
6var httpProxy = require('http-proxy');
7var logger = require('js-logger');
8var s = require('underscore.string');
9var _ = require('lodash');
10var uri = require('urijs');
11var tiny_lr = require('tiny-lr');
12var liveReload = require('connect-livereload');
13var body = require('body-parser');
14var runningAsScript = require.main === module;
15var configFile = process.env.HAWTIO_CONFIG_FILE || 'config.js';
16// default config values
17var config = {
18 // server listen port
19 port: 2772,
20 // log level
21 logLevel: logger.INFO,
22 // path to mount the dyamic proxy
23 proxy: '/proxy',
24 // paths to connect to external services, an example config:
25 // {
26 // proto: 'http',
27 // hostname: 'localhost',
28 // port: 8282,
29 // path: '/hawtio/jolokia',
30 // targetPath: '/hawtio/jolokia'
31 // }
32 //
33 staticProxies: [],
34 // directories to search for static assets
35 staticAssets: [
36 {
37 path: '/',
38 dir: '.'
39 }
40 ],
41 fallback: null,
42 liveReload: {
43 enabled: false,
44 port: 35729
45 }
46};
47if (fs.existsSync(configFile)) {
48 var conf = require(configFile);
49 _.assign(config, conf);
50}
51logger.useDefaults(config.logLevel);
52if (runningAsScript) {
53 logger.get('hawtio-backend').info("Running as script");
54}
55/// <reference path="includes.ts" />
56var HawtioBackend;
57(function (HawtioBackend) {
58 HawtioBackend.log = logger.get('hawtio-backend');
59 HawtioBackend.app = express();
60 HawtioBackend.proxyRoutes = {};
61 var startupTasks = [];
62 var listening = false;
63 function getTargetURI(options) {
64 var target = new uri({
65 protocol: options.proto,
66 hostname: options.hostname,
67 port: options.port,
68 path: options.path
69 });
70 target.query(options.query);
71 var targetURI = target.toString();
72 HawtioBackend.log.debug("Target URI: ", targetURI);
73 return targetURI;
74 }
75 HawtioBackend.getTargetURI = getTargetURI;
76 function addStartupTask(cb) {
77 HawtioBackend.log.debug("Adding startup task");
78 startupTasks.push(cb);
79 if (listening) {
80 cb();
81 }
82 }
83 HawtioBackend.addStartupTask = addStartupTask;
84 function setConfig(newConfig) {
85 _.assign(config, newConfig);
86 HawtioBackend.log.setLevel(config.logLevel);
87 }
88 HawtioBackend.setConfig = setConfig;
89 var server = null;
90 var lr = null;
91 var lrServer = null;
92 function reload() {
93 return eventStream.map(function (file, callback) {
94 if (lr) {
95 lr.changed({
96 body: {
97 files: file.path
98 }
99 });
100 }
101 return callback(null, file);
102 });
103 }
104 HawtioBackend.reload = reload;
105 function use(path, func) {
106 HawtioBackend.app.use(path, func);
107 }
108 HawtioBackend.use = use;
109 function listen(cb) {
110 var lrPort = config.liveReload.port || 35729;
111 if (config.liveReload.enabled) {
112 HawtioBackend.app.use(liveReload({ port: lrPort }));
113 }
114 listening = true;
115 startupTasks.forEach(function (cb) {
116 HawtioBackend.log.debug("Executing startup task");
117 cb();
118 });
119 if (config.fallback) {
120 HawtioBackend.app.use(function (req, res, next) {
121 fs.createReadStream(config.fallback).pipe(res);
122 });
123 }
124 server = HawtioBackend.app.listen(config.port, function () {
125 if (config.liveReload.enabled) {
126 lr = tiny_lr();
127 lrServer = lr.listen(lrPort, function () {
128 HawtioBackend.log.info("Started livereload, port :", lrPort);
129 });
130 }
131 cb(server);
132 });
133 server.on('upgrade', function (req, socket, head) {
134 //console.log("Upgrade event for URL: ", req.url);
135 var targetUri = new uri(req.url);
136 var targetPath = targetUri.path();
137 _.forIn(HawtioBackend.proxyRoutes, function (config, route) {
138 if (s.startsWith(targetPath, route)) {
139 //console.log("Found config for route: ", route, " config: ", config);
140 if (!config.httpProxy) {
141 var proxyConfig = config.proxyConfig;
142 var target = new uri().protocol(proxyConfig.proto).host(proxyConfig.hostname).port(proxyConfig.port).path(proxyConfig.targetPath).query({}).toString();
143 console.log("Creating websocket proxy to target: ", target);
144 config.proxy = httpProxy.createProxyServer({
145 target: target,
146 secure: false,
147 ws: true
148 });
149 }
150 targetPath = targetPath.substring(route.length);
151 req.url = targetUri.path(targetPath).toString();
152 config.proxy.ws(req, socket, head);
153 }
154 });
155 });
156 return server;
157 }
158 HawtioBackend.listen = listen;
159 function stop(cb) {
160 if (lrServer) {
161 lrServer.close(function () {
162 HawtioBackend.log.info("Stopped livereload port");
163 });
164 lrServer = null;
165 }
166 if (server) {
167 server.close(function () {
168 listening = false;
169 if (cb) {
170 cb();
171 }
172 });
173 server = null;
174 }
175 }
176 HawtioBackend.stop = stop;
177 function getServer() {
178 return server;
179 }
180 HawtioBackend.getServer = getServer;
181 if (runningAsScript) {
182 server = listen(function (server) {
183 var host = server.address().address;
184 var port = server.address().port;
185 HawtioBackend.log.info("started at ", host, ":", port);
186 });
187 }
188})(HawtioBackend || (HawtioBackend = {}));
189(module).exports = HawtioBackend;
190/// <reference path="init.ts" />
191var HawtioBackend;
192(function (HawtioBackend) {
193 function proxy(uri, req, res) {
194 function handleError(e) {
195 res.status(500).end('error proxying to "' + uri + '": ' + e);
196 }
197 var r = request({ method: req.method, uri: uri, json: req.body });
198 req.on('error', handleError)
199 .pipe(r)
200 .on('error', handleError)
201 .on('response', function (res2) {
202 if (res2.statusCode === 401 || res2.statusCode === 403) {
203 HawtioBackend.log.info("Authentication failed on remote server:", res2.statusCode, res2.statusMessage, uri);
204 HawtioBackend.log.debug("Response headers:\n", res2.headers);
205 res.header(res2.headers).sendStatus(res2.statusCode);
206 }
207 else {
208 res2.pipe(res).on('error', handleError);
209 }
210 });
211 }
212 HawtioBackend.addStartupTask(function () {
213 var index = 0;
214 config.staticProxies.forEach(function (proxyConfig) {
215 index = index + 1;
216 _.defaults(proxyConfig, {
217 path: '/proxy-' + index,
218 hostname: 'localhost',
219 port: 80,
220 proto: 'http',
221 targetPath: '/proxy-' + index
222 });
223 HawtioBackend.log.debug("adding static proxy config: \n", proxyConfig);
224 var router = express.Router();
225 router.use('/', function (req, res, next) {
226 var path = [s.rtrim(proxyConfig.targetPath, '/'), s.ltrim(req.path, '/')].join('/');
227 var uri = HawtioBackend.getTargetURI({
228 proto: proxyConfig.proto,
229 hostname: proxyConfig.hostname,
230 port: proxyConfig.port,
231 path: path,
232 query: req.query
233 });
234 proxy(uri, req, res);
235 });
236 HawtioBackend.app.use(proxyConfig.path, router);
237 HawtioBackend.proxyRoutes[proxyConfig.path] = {
238 proxyConfig: proxyConfig,
239 router: router
240 };
241 });
242 });
243 // dynamic proxy
244 var proxyRouter = express.Router();
245 proxyRouter.param('proto', function (req, res, next, proto) {
246 HawtioBackend.log.debug("requesting proto: ", proto);
247 switch (proto.toLowerCase()) {
248 case 'http':
249 case 'https':
250 next();
251 break;
252 default:
253 res.status(406).send('Invalid protocol: "' + proto + '"');
254 }
255 });
256 proxyRouter.param('hostname', function (req, res, next, hostname) {
257 HawtioBackend.log.debug("requesting hostname: ", hostname);
258 next();
259 });
260 proxyRouter.param('port', function (req, res, next, port) {
261 HawtioBackend.log.debug("requesting port: ", port);
262 var portNumber = s.toNumber(port);
263 HawtioBackend.log.debug("parsed port number: ", portNumber);
264 if (isNaN(portNumber)) {
265 res.status(406).send('Invalid port number: "' + port + '"');
266 }
267 else {
268 next();
269 }
270 });
271 proxyRouter.use('/', function (req, res, next) {
272 if (req.path === '') {
273 res.status(200).end();
274 }
275 else {
276 next();
277 }
278 });
279 proxyRouter.use('/:proto/:hostname/:port/', function (req, res, next) {
280 var uri = HawtioBackend.getTargetURI({
281 proto: req.params.proto,
282 hostname: req.params.hostname,
283 port: req.params.port,
284 path: req.path,
285 query: req.query
286 });
287 proxy(uri, req, res);
288 });
289 HawtioBackend.addStartupTask(function () {
290 HawtioBackend.log.debug("Setting dynamic proxy mount point: ", config.proxy);
291 HawtioBackend.app.use(config.proxy, proxyRouter);
292 });
293})(HawtioBackend || (HawtioBackend = {}));
294/// <reference path="init.ts"/>
295var HawtioBackend;
296(function (HawtioBackend) {
297 function mountAsset(mount, dir) {
298 HawtioBackend.app.use(mount, express.static(path.normalize(dir)));
299 }
300 HawtioBackend.mountAsset = mountAsset;
301 HawtioBackend.addStartupTask(function () {
302 config.staticAssets.forEach(function (asset) {
303 HawtioBackend.log.info("Mounting static asset: ", asset);
304 mountAsset(asset.path, asset.dir);
305 });
306 });
307})(HawtioBackend || (HawtioBackend = {}));