1 | var path = require('path');
|
2 | var fs = require('fs');
|
3 | var temp = require('temp');
|
4 | var url = require('url');
|
5 |
|
6 | var async = require("async");
|
7 |
|
8 | var util = require("./util/util");
|
9 | var legacy = require("./util/legacy");
|
10 |
|
11 | var http = require('http');
|
12 | var https = require('https');
|
13 |
|
14 |
|
15 | var Gitana = require("gitana");
|
16 |
|
17 |
|
18 | process.defaultHttpTimeoutMs = 120000;
|
19 |
|
20 | if (process.env.DEFAULT_HTTP_TIMEOUT_MS)
|
21 | {
|
22 | try
|
23 | {
|
24 | process.defaultHttpTimeoutMs = parseInt(process.env.DEFAULT_HTTP_TIMEOUT_MS);
|
25 | }
|
26 | catch (e)
|
27 | {
|
28 |
|
29 | }
|
30 | }
|
31 |
|
32 |
|
33 | var HttpKeepAliveAgent = require('agentkeepalive');
|
34 | var HttpsKeepAliveAgent = require('agentkeepalive').HttpsAgent;
|
35 | http.globalAgent = new HttpKeepAliveAgent({
|
36 | keepAlive: true,
|
37 | keepAliveMsecs: 1000,
|
38 | keepAliveTimeout: 30000,
|
39 | timeout: process.defaultHttpTimeoutMs,
|
40 | maxSockets: 200,
|
41 | maxFreeSockets: 40,
|
42 | rejectUnauthorized: false
|
43 | });
|
44 | https.globalAgent = new HttpsKeepAliveAgent({
|
45 | keepAlive: true,
|
46 | keepAliveMsecs: 1000,
|
47 | keepAliveTimeout: 30000,
|
48 | timeout: process.defaultHttpTimeoutMs,
|
49 | maxSockets: 200,
|
50 | maxFreeSockets: 40,
|
51 | rejectUnauthorized: false
|
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 | require("ssl-root-cas").inject();
|
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 | exports = module.exports = function()
|
103 | {
|
104 |
|
105 | temp.track();
|
106 |
|
107 |
|
108 |
|
109 | console.warn = function() {};
|
110 |
|
111 | process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
112 |
|
113 |
|
114 | if (!process.env.CLOUDCMS_APPSERVER_BASE_PATH) {
|
115 | process.env.CLOUDCMS_APPSERVER_BASE_PATH = process.cwd();
|
116 | }
|
117 |
|
118 |
|
119 |
|
120 | var defaultGitanaProxyScheme = legacy.DEFAULT_GITANA_PROXY_SCHEME;
|
121 | var defaultGitanaProxyHost = legacy.DEFAULT_GITANA_PROXY_HOST;
|
122 | var defaultGitanaProxyPort = legacy.DEFAULT_GITANA_PROXY_PORT;
|
123 |
|
124 | var gitanaJsonPath = path.join(process.env.CLOUDCMS_APPSERVER_BASE_PATH, "gitana.json");
|
125 | if (fs.existsSync(gitanaJsonPath))
|
126 | {
|
127 | var gitanaJson = util.jsonParse("" + fs.readFileSync(gitanaJsonPath));
|
128 | if (gitanaJson && gitanaJson.baseURL)
|
129 | {
|
130 | var parsedUrl = url.parse(gitanaJson.baseURL);
|
131 |
|
132 | defaultGitanaProxyHost = parsedUrl.hostname;
|
133 | defaultGitanaProxyScheme = parsedUrl.protocol.substring(0, parsedUrl.protocol.length - 1);
|
134 |
|
135 | if (parsedUrl.port)
|
136 | {
|
137 | defaultGitanaProxyPort = parsedUrl.port;
|
138 | }
|
139 | else
|
140 | {
|
141 | defaultGitanaProxyPort = 80;
|
142 | if (defaultGitanaProxyScheme === "https")
|
143 | {
|
144 | defaultGitanaProxyPort = 443;
|
145 | }
|
146 | }
|
147 | }
|
148 | }
|
149 |
|
150 |
|
151 | if (!process.env.GITANA_PROXY_SCHEME) {
|
152 | process.env.GITANA_PROXY_SCHEME = defaultGitanaProxyScheme;
|
153 | }
|
154 | if (!process.env.GITANA_PROXY_HOST) {
|
155 | process.env.GITANA_PROXY_HOST = defaultGitanaProxyHost;
|
156 | }
|
157 | if (!process.env.GITANA_PROXY_PORT) {
|
158 | process.env.GITANA_PROXY_PORT = defaultGitanaProxyPort;
|
159 | }
|
160 |
|
161 |
|
162 | process.env.GITANA_PROXY_HOST = legacy.autoUpgrade(process.env.GITANA_PROXY_HOST, true);
|
163 |
|
164 | console.log("Gitana Proxy pointed to: " + util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT));
|
165 |
|
166 |
|
167 | if (!process.includeWebModule) {
|
168 | process.includeWebModule = function(host, moduleId) {
|
169 | return true;
|
170 | };
|
171 | }
|
172 |
|
173 |
|
174 | var admin = require("./middleware/admin/admin");
|
175 | var authentication = require("./middleware/authentication/authentication");
|
176 | var authorization = require("./middleware/authorization/authorization");
|
177 | var cache = require("./middleware/cache/cache");
|
178 | var cloudcms = require("./middleware/cloudcms/cloudcms");
|
179 | var config = require("./middleware/config/config");
|
180 | var debug = require("./middleware/debug/debug");
|
181 | var deployment = require("./middleware/deployment/deployment");
|
182 | var driver = require("./middleware/driver/driver");
|
183 | var driverConfig = require("./middleware/driver-config/driver-config");
|
184 | var final = require("./middleware/final/final");
|
185 | var flow = require("./middleware/flow/flow");
|
186 | var form = require("./middleware/form/form");
|
187 | var healthcheck = require("./middleware/healthcheck/healthcheck");
|
188 | var host = require("./middleware/host/host");
|
189 | var graphql = require("./middleware/graphql/graphql");
|
190 | var libraries = require("./middleware/libraries/libraries");
|
191 | var local = require("./middleware/local/local");
|
192 | var locale = require("./middleware/locale/locale");
|
193 | var modules = require("./middleware/modules/modules");
|
194 | var perf = require("./middleware/perf/perf");
|
195 | var proxy = require("./middleware/proxy/proxy");
|
196 | var registration = require("./middleware/registration/registration");
|
197 | var resources = require("./middleware/resources/resources");
|
198 | var runtime = require("./middleware/runtime/runtime");
|
199 | var serverTags = require("./middleware/server-tags/server-tags");
|
200 | var storeService = require("./middleware/stores/stores");
|
201 | var templates = require("./middleware/templates/templates");
|
202 | var virtualConfig = require("./middleware/virtual-config/virtual-config");
|
203 | var virtualFiles = require("./middleware/virtual-files/virtual-files");
|
204 | var wcm = require("./middleware/wcm/wcm");
|
205 | var welcome = require("./middleware/welcome/welcome");
|
206 | var awareness = require("./middleware/awareness/awareness");
|
207 | var userAgent = require('express-useragent');
|
208 |
|
209 |
|
210 | var notifications = require("./notifications/notifications");
|
211 | var broadcast = require("./broadcast/broadcast");
|
212 | var locks = require("./locks/locks");
|
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 | var packageJsonPath = path.resolve(__dirname, "package.json");
|
219 | if (fs.existsSync(packageJsonPath))
|
220 | {
|
221 | var packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString());
|
222 |
|
223 | process.env.CLOUDCMS_APPSERVER_PACKAGE_NAME = packageJson.name;
|
224 | process.env.CLOUDCMS_APPSERVER_PACKAGE_VERSION = packageJson.version;
|
225 | }
|
226 |
|
227 |
|
228 | var r = {};
|
229 |
|
230 | r.init = function(app, callback)
|
231 | {
|
232 | if (process.configuration && process.configuration.gitana)
|
233 | {
|
234 | if (typeof(process.configuration.gitana.httpWorkQueueSize) !== "undefined")
|
235 | {
|
236 | if (process.configuration.gitana.httpWorkQueueSize > -1)
|
237 | {
|
238 | Gitana.HTTP_WORK_QUEUE_SIZE = process.configuration.gitana.httpWorkQueueSize;
|
239 |
|
240 | console.log("Limiting Gitana Driver HTTP work queue to size: " + Gitana.HTTP_WORK_QUEUE_SIZE);
|
241 | }
|
242 | }
|
243 | }
|
244 |
|
245 | process.cache = app.cache = cache;
|
246 | process.broadcast = app.broadcast = broadcast;
|
247 | process.locks = app.locks = locks;
|
248 | process.authentication = app.authentication = authentication;
|
249 |
|
250 |
|
251 | app.filter = process.authentication.filter;
|
252 |
|
253 | var fns = [
|
254 | locks.init,
|
255 | broadcast.start,
|
256 | storeService.init,
|
257 | notifications.start,
|
258 | cache.init,
|
259 | awareness.init
|
260 | ];
|
261 | async.series(fns, function(err) {
|
262 | callback(err);
|
263 | });
|
264 | };
|
265 |
|
266 | r.common1 = function(app)
|
267 | {
|
268 |
|
269 | applyApplicationConfiguration(app);
|
270 |
|
271 |
|
272 | app.use(locale.localeInterceptor());
|
273 |
|
274 |
|
275 | app.use(host.hostInterceptor());
|
276 | };
|
277 |
|
278 | r.common2 = function(app)
|
279 | {
|
280 |
|
281 | app.use(storeService.storesInterceptor());
|
282 |
|
283 |
|
284 | app.use(virtualFiles.interceptor());
|
285 |
|
286 |
|
287 | app.use(runtime.interceptor());
|
288 |
|
289 |
|
290 |
|
291 | app.use(virtualConfig.interceptor());
|
292 |
|
293 |
|
294 | app.use(driverConfig.interceptor());
|
295 | };
|
296 |
|
297 | r.common3 = function(app)
|
298 | {
|
299 |
|
300 | app.use(driver.driverInterceptor());
|
301 | };
|
302 |
|
303 | r.common4 = function(app, includeCloudCMS)
|
304 | {
|
305 | var configuration = app.configuration;
|
306 |
|
307 | if (includeCloudCMS)
|
308 | {
|
309 |
|
310 | app.use(cache.cacheInterceptor());
|
311 |
|
312 |
|
313 | app.use(cloudcms.applicationInterceptor());
|
314 |
|
315 |
|
316 | app.use(cloudcms.applicationSettingsInterceptor());
|
317 |
|
318 |
|
319 | app.use(cloudcms.repositoryInterceptor());
|
320 |
|
321 |
|
322 |
|
323 | app.use(cloudcms.branchInterceptor());
|
324 |
|
325 |
|
326 | app.use(cloudcms.domainInterceptor());
|
327 |
|
328 |
|
329 |
|
330 |
|
331 |
|
332 | app.use(cloudcms.cmsLogInterceptor());
|
333 | }
|
334 |
|
335 |
|
336 | app.use(graphql.interceptor());
|
337 | };
|
338 |
|
339 | r.perf1 = function(app)
|
340 | {
|
341 | app.use(perf.pathPerformanceInterceptor());
|
342 | };
|
343 |
|
344 | r.proxy = function(app)
|
345 | {
|
346 | app.use(proxy.proxy());
|
347 | };
|
348 |
|
349 | r.perf2 = function(app)
|
350 | {
|
351 | app.use(perf.mimeTypePerformanceInterceptor());
|
352 | };
|
353 |
|
354 | r.perf3 = function(app)
|
355 | {
|
356 | app.use(perf.developmentPerformanceInterceptor());
|
357 | };
|
358 |
|
359 | var applyApplicationConfiguration = r.applyApplicationConfiguration = function(app)
|
360 | {
|
361 |
|
362 | app.use(function(req, res, next) {
|
363 |
|
364 | var finish = function(configuration)
|
365 | {
|
366 | req.configuration = function(name, callback)
|
367 | {
|
368 | if (typeof(name) === "function")
|
369 | {
|
370 | return callback(null, configuration);
|
371 | }
|
372 |
|
373 | if (!name)
|
374 | {
|
375 | return callback();
|
376 | }
|
377 |
|
378 | callback(null, configuration[name]);
|
379 | };
|
380 |
|
381 | req.isEnabled = function(name)
|
382 | {
|
383 | return (configuration && configuration[name] && configuration[name].enabled);
|
384 | };
|
385 |
|
386 | next();
|
387 | };
|
388 |
|
389 | var configuration = util.clone(process.configuration);
|
390 |
|
391 | if (req.application)
|
392 | {
|
393 | req.application(function(err, application) {
|
394 |
|
395 | if (application)
|
396 | {
|
397 | var applicationConfiguration = application.runtime;
|
398 | if (applicationConfiguration)
|
399 | {
|
400 |
|
401 | util.merge(applicationConfiguration, configuration);
|
402 | }
|
403 |
|
404 | finish(configuration);
|
405 | }
|
406 | else
|
407 | {
|
408 | finish(configuration);
|
409 | }
|
410 |
|
411 | });
|
412 | }
|
413 | else
|
414 | {
|
415 | finish(configuration);
|
416 | }
|
417 | });
|
418 | };
|
419 |
|
420 | r.welcome = function(app)
|
421 | {
|
422 |
|
423 | app.use(welcome.welcomeInterceptor());
|
424 | };
|
425 |
|
426 | r.healthcheck = function(app)
|
427 | {
|
428 |
|
429 | app.use(healthcheck.handler());
|
430 | };
|
431 |
|
432 | r.interceptors = function(app, includeCloudCMS)
|
433 | {
|
434 | var configuration = app.configuration;
|
435 |
|
436 |
|
437 | app.use(authentication.interceptor());
|
438 |
|
439 |
|
440 | app.use(authorization.authorizationInterceptor());
|
441 |
|
442 |
|
443 | app.use(config.remoteConfigInterceptor());
|
444 |
|
445 |
|
446 | app.use(serverTags.interceptor(configuration));
|
447 |
|
448 | if (includeCloudCMS)
|
449 | {
|
450 |
|
451 | app.use(wcm.wcmInterceptor());
|
452 | }
|
453 | };
|
454 |
|
455 | r.handlers = function(app, includeCloudCMS)
|
456 | {
|
457 | if (includeCloudCMS)
|
458 | {
|
459 |
|
460 | app.use(cloudcms.authenticationHandler(app));
|
461 | }
|
462 |
|
463 |
|
464 | app.use(awareness.handler());
|
465 |
|
466 |
|
467 | app.use(admin.handler());
|
468 |
|
469 |
|
470 | app.use(debug.handler());
|
471 |
|
472 |
|
473 | app.use(deployment.handler());
|
474 |
|
475 |
|
476 | app.use(config.staticConfigHandler());
|
477 |
|
478 |
|
479 | app.use(config.remoteConfigHandler());
|
480 |
|
481 |
|
482 | app.use(templates.handler());
|
483 |
|
484 |
|
485 | app.use(modules.handler());
|
486 |
|
487 |
|
488 | app.use(resources.handler());
|
489 |
|
490 |
|
491 | app.use(libraries.handler());
|
492 |
|
493 |
|
494 | app.use(authentication.handler(app));
|
495 |
|
496 | if (includeCloudCMS)
|
497 | {
|
498 |
|
499 | app.use(cloudcms.virtualNodeHandler());
|
500 |
|
501 |
|
502 | app.use(cloudcms.virtualPrincipalHandler());
|
503 | }
|
504 |
|
505 |
|
506 | app.use(registration.handler());
|
507 |
|
508 |
|
509 | app.use(flow.handlers());
|
510 |
|
511 |
|
512 | app.use(form.formHandler());
|
513 |
|
514 |
|
515 | app.use(runtime.handler());
|
516 |
|
517 |
|
518 |
|
519 |
|
520 |
|
521 | app.use(local.defaultHandler());
|
522 |
|
523 |
|
524 | app.use(userAgent.express());
|
525 |
|
526 | if (includeCloudCMS)
|
527 | {
|
528 |
|
529 | app.use(wcm.wcmHandler());
|
530 | }
|
531 |
|
532 |
|
533 | app.use(final.finalHandler());
|
534 | };
|
535 |
|
536 | r.bodyParser = function()
|
537 | {
|
538 | return function(req, res, next)
|
539 | {
|
540 | if (req._body)
|
541 | {
|
542 | return next();
|
543 | }
|
544 |
|
545 | var contentType = req.get("Content-Type");
|
546 |
|
547 | if (req.method.toLowerCase() == "post") {
|
548 |
|
549 | req._body = true;
|
550 |
|
551 | var responseString = "";
|
552 |
|
553 | req.on('data', function(data) {
|
554 | responseString += data;
|
555 | });
|
556 |
|
557 | req.on('end', function() {
|
558 |
|
559 | if (responseString.length > 0) {
|
560 |
|
561 | try {
|
562 | var b = JSON.parse(responseString);
|
563 | if (b)
|
564 | {
|
565 | req.body = b;
|
566 | }
|
567 | } catch (e) { }
|
568 | }
|
569 |
|
570 | next();
|
571 | });
|
572 | }
|
573 | else
|
574 | {
|
575 | next();
|
576 | }
|
577 | };
|
578 | };
|
579 |
|
580 | |
581 |
|
582 |
|
583 |
|
584 |
|
585 | r.ensureCORS = function()
|
586 | {
|
587 | return util.createInterceptor("cors", function(req, res, next, stores, cache, configuration) {
|
588 |
|
589 | var origin = configuration.origin;
|
590 | if (!origin)
|
591 | {
|
592 | origin = req.headers["origin"];
|
593 | }
|
594 | if (!origin)
|
595 | {
|
596 | origin = req.headers["x-cloudcms-origin"];
|
597 | }
|
598 | if (!origin)
|
599 | {
|
600 | origin = "*";
|
601 | }
|
602 |
|
603 | var methods = configuration.methods;
|
604 | var headers = configuration.headers;
|
605 | var credentials = configuration.credentials;
|
606 |
|
607 | util.setHeaderOnce(res, "Access-Control-Allow-Origin", origin);
|
608 |
|
609 | if (methods)
|
610 | {
|
611 | util.setHeaderOnce(res, "Access-Control-Allow-Methods", methods);
|
612 | }
|
613 |
|
614 | if (headers)
|
615 | {
|
616 | util.setHeaderOnce(res, "Access-Control-Allow-Headers", headers);
|
617 | }
|
618 |
|
619 | if (credentials)
|
620 | {
|
621 | util.setHeaderOnce(res, "Access-Control-Allow-Credentials", "" + credentials);
|
622 | }
|
623 |
|
624 |
|
625 |
|
626 | if ('OPTIONS' === req.method) {
|
627 | return res.sendStatus(200);
|
628 | }
|
629 |
|
630 | next();
|
631 | });
|
632 | };
|
633 |
|
634 | r.ensureHeaders = function()
|
635 | {
|
636 | return function(req, res, next) {
|
637 |
|
638 |
|
639 | var xFrameOptions = "SAMEORIGIN";
|
640 | var xXssProtection = "1; mode=block";
|
641 |
|
642 |
|
643 |
|
644 | if (xFrameOptions)
|
645 | {
|
646 | util.setHeaderOnce(res, "X-Frame-Options", xFrameOptions);
|
647 | }
|
648 |
|
649 | if (xXssProtection)
|
650 | {
|
651 | util.setHeaderOnce(res, "X-XSS-Protection", xXssProtection)
|
652 | }
|
653 |
|
654 | util.setHeaderOnce(res, "X-Powered-By", "Cloud CMS");
|
655 |
|
656 | next();
|
657 | };
|
658 | };
|
659 |
|
660 | var stringifyError = function(err)
|
661 | {
|
662 | var stack = err.stack;
|
663 |
|
664 | if (stack) {
|
665 | return String(stack)
|
666 | }
|
667 |
|
668 | return JSON.stringify(err, null, " ");
|
669 | };
|
670 |
|
671 |
|
672 | r.consoleErrorLogger = function(app, callback)
|
673 | {
|
674 |
|
675 | app.use(function(err, req, res, next) {
|
676 |
|
677 | console.error(stringifyError(err));
|
678 |
|
679 | next(err);
|
680 | });
|
681 |
|
682 | callback();
|
683 | };
|
684 |
|
685 | var errorHandler = require("errorhandler");
|
686 |
|
687 | r.refreshTokenErrorHandler = function(app, callback)
|
688 | {
|
689 | app.use(function(err, req, res, next) {
|
690 |
|
691 | if (err)
|
692 | {
|
693 | if (req.method.toLowerCase() === "get")
|
694 | {
|
695 | if (err.status === 401)
|
696 | {
|
697 | if (err.message)
|
698 | {
|
699 | if (err.message.toLowerCase().indexOf("expired") > -1)
|
700 | {
|
701 | if (err.message.toLowerCase().indexOf("refresh") > -1)
|
702 | {
|
703 | var url = req.path;
|
704 |
|
705 | console.log("Refresh Token Expired, re-requesting resource: " + url);
|
706 |
|
707 | var html = "";
|
708 | html += "<html>";
|
709 | html += "<head>";
|
710 | html += "<meta http-equiv='refresh' content='1;URL=" + url + "'>";
|
711 | html += "</head>";
|
712 | html += "<body>";
|
713 | html += "</body>";
|
714 | html += "</html>";
|
715 |
|
716 | return res.status(200).type("text/html").send(html);
|
717 | }
|
718 | }
|
719 | }
|
720 | }
|
721 | }
|
722 | }
|
723 |
|
724 | next(err);
|
725 | });
|
726 |
|
727 | callback();
|
728 | };
|
729 |
|
730 | r.defaultErrorHandler = function(app, callback)
|
731 | {
|
732 | app.use(function(err, req, res, next) {
|
733 |
|
734 |
|
735 | errorHandler()(err, req, res, next);
|
736 | });
|
737 |
|
738 | callback();
|
739 | };
|
740 |
|
741 | return r;
|
742 | }();
|