UNPKG

2.94 kBJavaScriptView Raw
1const express = require('express');
2const get = require('lodash/get');
3
4const helmet = require('./middlewares/helmet');
5const cors = require('./middlewares/cors');
6
7const {
8 createRequestLogger,
9 createErrorLogger,
10 loggerMiddleware,
11 genStackdriverLogTraceMw
12} = require('./log');
13
14const genApp = (opts = {}) => {
15
16 const {
17 logger,
18 sd_mw
19 } = opts;
20
21 const app = express();
22
23 app.use(helmet());
24 app.use(cors());
25
26 app.set('trust proxy', true);
27
28 //TODO: make this GAE functionality overwriteable
29 //https://cloud.google.com/appengine/docs/standard/nodejs/how-instances-are-managed
30 app.use('/_ah/start', (req, res) => res.json({success: true}));
31 app.use('/_ah/stop', (req, res) => res.json({success: true}));
32 app.use('/_ah/warmup', (req, res) => res.json({success: true})); //not for manual or basic scaling instances
33 app.use('/_ah/health_check', (req, res) => res.json({success: true}));
34
35 if (logger) {
36 app.use(createRequestLogger({logger}));
37 app.logger = logger; //global scoped logger req.app.logger
38
39 if (typeof sd_mw !== 'function') {
40 app.use(loggerMiddleware({logger}));
41 }
42 }
43
44 if (typeof sd_mw === 'function')
45 app.use(sd_mw); //enables Google Trace + request scoped req.log interface
46
47 if (sd_mw === true)
48 return genStackdriverLogTraceMw(logger)
49 .then(sd_mw => {
50 app.use(sd_mw);
51 return app;
52 })
53 ;
54
55 return app;
56};
57
58const addErrorHandler = (app, logger, debug) => {
59
60 const isProduction = process.env.NODE_ENV === 'production';
61 const showStack = !isProduction || process.env.DEBUG || debug;
62
63 //express-winston logger
64 if (logger)
65 app.use(createErrorLogger({logger}));
66
67 app.use((err, req, res, next) => {
68
69 const log = req.log || logger;
70
71 //log exception to trigger stackdriver push notifications
72 const shouldTriggerError = isProduction && (!err.statusCode || err.statusCode >= 500);
73 if (log && shouldTriggerError)
74 log.error(err.message, err);
75
76 res.status(err.statusCode || 500).json({
77 success: false,
78 error: {
79 message: get(err, 'originalError.message', err.message),
80 code: get(err, 'originalError.code', err.code),
81 stack: showStack ? err.stack.split('\n') : undefined
82 }
83 });
84 });
85};
86
87const addApiServiceRoutes = (app, path, routes, serviceName) => {
88 //add routes like normal
89 app.use(path, routes);
90
91 //if serviceName given, expose routes als as /api/servicename/...
92 if (serviceName)
93 app.use(`/api/${serviceName}${path}`, routes);
94};
95
96module.exports = {
97 genApp,
98 static: express.static,
99 Router: express.Router,
100 createErrorLogger,
101 addErrorHandler,
102 addApiServiceRoutes
103};
\No newline at end of file