This commit is contained in:
2026-04-07 14:50:23 +09:00
commit b4e485502b
4778 changed files with 2017091 additions and 0 deletions

993
safekiso-server/app.js Normal file
View File

@@ -0,0 +1,993 @@
var utils = require('./src/utils');
var crossCtl = require('./src/crossCtl');
var compression = require('compression');
var express = require('express');
// var cors = require('cors')
var path = require('path');
var morgan = require('morgan');
var rfs = require('rotating-file-stream'); // version 2.x
var favicon = require('serve-favicon');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var FacebookStrategy = require('passport-facebook').Strategy;
var GoogleStrategy = require('passport-google-oauth20').Strategy;
var KakaoStrategy = require('passport-kakao').Strategy;
var AppleStrategy = require('passport-apple');
var CustomStrategy = require('passport-custom').Strategy;
var mysql = require('mysql');
var moment = require('moment');
var app = express();
app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ limit: '50mb', extended: false }));
app.set('trust proxy', true);
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
var sessionDomain = 'safekiso.com';
// // console.log('huk sessionDomain = ', sessionDomain)
var redisOptions = {};
if (crossCtl.sConfig.redis) {
redisOptions = {
...crossCtl.config.options.redis,
...crossCtl.sConfig.redis,
};
} else {
redisOptions = { ...crossCtl.config.options.redis };
}
// console.log('huk redisOptions = ', redisOptions)
var cookieOptions = {};
if (crossCtl.sConfig.cookie) {
cookieOptions = crossCtl.sConfig.cookie;
} else {
cookieOptions = {
path: '/',
// sameSite: 'strict',
// domain: sessionDomain, // !!!!!!!
// maxAge: 1000 * 60 * 60 * 24 // 24 hours
maxAge: 1000 * 60 * 60 * 1, // 1 hours
};
}
// console.log('huk cookieOptions = ', cookieOptions)
// redirect HTTP to HTTPS
app.all('*', (req, res, next) => {
let protocol = req.headers['x-forwarded-proto'] || req.protocol;
// console.log('protocol=', protocol)
if (protocol == 'https') {
next();
} else {
if (crossCtl.sConfig.forceHttps === true) {
let from = `${protocol}://${req.hostname}${req.url}`;
let to = `https://${req.hostname}${req.url}`;
// log and redirect
console.log(`[${req.method}]: ${from} -> ${to}`);
res.redirect(to);
} else {
next();
}
}
});
app.use(
session({
store: new RedisStore(redisOptions),
secret: 'in got we trust!!!',
resave: true,
saveUninitialized: true,
// ttl: 60 * 1,
rolling: true,
cookie: cookieOptions,
})
);
app.use(function (req, res, next) {
const cleanup = () => {
res.removeListener('finish', logStatsics);
res.removeListener('close', abortFn);
res.removeListener('error', errorFn);
};
const logStatsics = () => {
cleanup();
// console.log('logStatsics()')
// console.info(`${req.method} ${req.originalUrl}`)
// console.info(`${req.sessionID}`)
// crossCtl.redis.logHit(req.originalUrl)
if (req.sessionID) {
crossCtl.redis.logSession(req.sessionID);
} else {
// console.log('no session request!!!')
}
};
const abortFn = () => {
console.warn('Request aborted by the client');
cleanup();
};
const errorFn = (err) => {
console.error(`Request pipeline error: ${err}`);
cleanup();
};
res.on('finish', logStatsics); // successful pipeline (regardless of its response)
res.on('close', abortFn); // aborted pipeline
res.on('error', errorFn); // pipeline internal error
next();
});
app.use(compression());
// app.use(cors())
// view engine setup
app.set('view engine', 'ejs');
// var i18n = require('i18n')
crossCtl.i18n.configure({
locales: ['ko', 'en'],
defaultLocale: 'ko',
autoReload: true, // watch for changes in json files to reload locale on updates - defaults to false
updateFiles: true, // whether to write new locale information to disk - defaults to true
syncFiles: true, // sync locale information across all files - defaults to false
directory: path.join(__dirname, 'modules', crossCtl.sConfig.type, 'locales'),
});
// i18n.setLocale('ko');
app.use(crossCtl.i18n.init);
// uncomment after placing your favicon in /public
var morganOptions = {
skip: function (req, res) {
return req.url === '/ping';
},
};
// app.use(logger('dev', morganOptions))
// morgan
// create a rotating write stream
var accessLogStream = rfs.createStream(utils.generator, {
// interval: '1M', // rotate monthly
// interval: '1m', // rotate minitly
// immutable: true,
// rotate: 1,
// size: "30K",
interval: '1M', // rotate minitly
path: path.join(__dirname, crossCtl.sConfig.log),
});
accessLogStream.on('open', (filename) => {
// console.log('accessLogStream on open with ', filename)
});
accessLogStream.on('rotation', () => {
// console.log('accessLogStream on rotation')
});
accessLogStream.on('rotated', (filename) => {
// console.log('accessLogStream on rotated to ', filename)
});
accessLogStream.on('warning', (error) => {
// console.log('accessLogStream on warning with ', error )
});
accessLogStream.on('error', (error) => {
// console.log('accessLogStream on error with ', error )
});
// setup the logger
// morgan.token('trueIp', req => utils.getIPFromReq(req));
/*
morgan.token('remote-addr', function (req) {
return utils.getIPFromReq(req)
});
*/
app.use(morgan('combined', { stream: accessLogStream }));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// app.use(bodyParser.json({limit: '10mb', extended: true}))
// app.use(bodyParser.urlencoded({limit: '10mb', extended: true}))
app.use(cookieParser());
app.set('views', [
path.join(__dirname, 'modules', 'base', 'views'),
path.join(__dirname, 'modules', crossCtl.sConfig.type, 'views'),
]);
// app.set("views", path.join(__dirname, "modules", "base", "views"));
// app.set("views",path.join(__dirname, "modules", crossCtl.sConfig.type, "views"));
/*
app.use(
favicon(
path.join(
__dirname,
'modules',
crossCtl.sConfig.type,
'wwwroot',
'favicon.ico'
)
)
);
*/
//
if (crossCtl.sConfig.clientDistInfo != undefined) {
app.use(
express.static(
path.join(
__dirname,
'modules',
crossCtl.sConfig.type,
'client',
// crossCtl.sConfig.clientDistInfo.fromPath,
'.output',
'public'
)
)
);
}
app.use(
express.static(
path.join(__dirname, 'modules', crossCtl.sConfig.type, 'wwwroot')
)
);
app.use(express.static(path.join(__dirname, 'modules', 'base', 'wwwroot')));
app.use(
express.static(path.join(__dirname, 'modules', 'base', 'wwwroot', 'admindek'))
);
const fs = require('fs');
/*
if (crossCtl.sConfig.type === 'inspond') {
var wwwrootPath = path.join(__dirname, '..', 'wwwroot');
// console.log('wwwrootPath=', wwwrootPath)
if (fs.existsSync(wwwrootPath)) {
app.use(express.static(wwwrootPath));
}
}
*/
/*
crossCtl.text2png.generatePngFromText('졸리\n만세!', {}, 'modules/linkcare/wwwroot/out.png', (err) => {
console.log('after generatePngFromText(), err=', err)
})
*/
app.use(passport.initialize());
app.use(passport.session());
var passportOptions = crossCtl.sConfig.passport; // crossCtl.config.options.passport
function doAuth(type, key, token, info, cb) {
// var qry = 'SELECT * FROM ' + crossCtl.db.options.database + '.tbl_account_users WHERE auth_type = ' + type + ' AND auth_key = ' + mysql.escape(key) + ' AND status = 0'
var qry =
'SELECT * FROM ' +
crossCtl.db.options.database +
'.tbl_account_users WHERE auth_type = ' +
type +
' AND auth_key = ' +
mysql.escape(key) +
' AND site_id = ' +
mysql.escape(crossCtl.sConfig.type);
if (crossCtl.sConfig.type == 'usm') {
var roleTag = info.roleTag ? info.roleTag : 'student';
qry =
'SELECT * FROM ' +
crossCtl.db.options.database +
'.tbl_account_users WHERE auth_type = ' +
type +
' AND auth_key = ' +
mysql.escape(key) +
' AND site_id = ' +
mysql.escape(crossCtl.sConfig.type) +
' AND role_tag = ' +
mysql.escape(roleTag);
}
var prefDataJson = {};
var resultUser = {
auth_flag: false,
auth_type: type,
reason: 'undefined',
code: 0,
};
crossCtl.db.doEasyQuery(qry, function (err, results) {
if (err) {
cb(err, null);
} else {
if (results.length === 0) {
if (type === 0) {
// local인 경우 로그인 못한다고 하세요.
resultUser.reason = 'no user found';
resultUser.code = -1;
cb(new Error(resultUser.reason), resultUser);
// crossCtl.logUserAction('anonym', '404', 'bad login id, type = ' + type + ', key = ' + key + ', token = ' + token)
} else {
// 외부인 경우 레코드를 생성하고 리턴 합니다.
prefDataJson.account_info = info;
// console.log('info =', info)
// console.log('info.displayName =', info.displayName)
var post = {
site_id: crossCtl.sConfig.type,
name: info.name,
auth_type: type,
auth_key: key,
auth_token: token,
pref_data: JSON.stringify(prefDataJson),
};
qry =
'INSERT INTO ' +
crossCtl.db.options.database +
'.tbl_account_users SET ? ';
crossCtl.db.doEasyQueryPost(qry, post, function (err, results) {
if (err) {
resultUser.reason = err.message;
resultUser.code = utils.__line();
cb(err, resultUser);
} else {
var serial = results.insertId;
var uid = utils.uuid('uid_' + serial);
crossCtl.logUserAction(uid, 'new', JSON.stringify(info));
qry =
'UPDATE ' +
crossCtl.db.options.database +
'.tbl_account_users SET uid = ' +
mysql.escape(uid) +
' WHERE serial = ' +
serial;
crossCtl.db.doEasyQuery(qry, function (err, results) {
if (err) {
cb(err, null);
} else {
var user = {
site_id: crossCtl.sConfig.type,
uid: uid,
name: post.name,
auth_flag: true,
user_info: info,
account_info: post,
prefDataJson: prefDataJson,
newAccountFlag: true,
created: moment.utc().format(),
};
crossCtl.passEventToLocalHandler(
'addUser',
user,
function (error) {
if (error) {
utils.log(
'error',
'on crossCtl.passEventToLocalHandler(), error =',
error
);
}
if (crossCtl.sConfig.allowSignup === false) {
resultUser.reason = 'no signup allowded';
resultUser.code = -10;
cb(new Error(resultUser.reason), resultUser);
} else {
crossCtl.loadProfile(user, cb);
// cb(error, user)
}
}
);
// crossCtl.logUserAction(uid, 'login', 'login ok')
}
});
}
});
}
} else if (results.length > 1) {
resultUser.reason = 'too many target';
resultUser.code = utils.__line();
cb(new Error('too many target account found'), resultUser);
} else {
// 1개의 레코드가 있군요. 비교하세요.
if (type === 0) {
if (results[0].status !== 0) {
resultUser.reason = 'bad status : ' + results[0].status;
resultUser.code = -2;
cb(new Error(resultUser.reason), resultUser);
} else if (results[0].bad_pass_count >= 5) {
resultUser.reason =
'wrong password count limit exceeded : ' +
results[0].bad_pass_count;
resultUser.code = -2;
cb(new Error(resultUser.reason), resultUser);
} else {
utils.compareHash(
token,
results[0].auth_token,
function (err, result) {
if (err) {
resultUser.reason = err.message;
resultUser.code = utils.__line();
cb(err, resultUser);
} else {
if (result === false) {
resultUser.reason = 'bad password';
resultUser.code = -2;
cb(new Error(resultUser.reason), resultUser);
qry =
'UPDATE ' +
crossCtl.db.options.database +
'.tbl_account_users SET bad_pass_count = bad_pass_count + 1 WHERE auth_type = ' +
type +
' AND auth_key = ' +
mysql.escape(key) +
' AND site_id = ' +
mysql.escape(crossCtl.sConfig.type);
crossCtl.db.doEasyQuery(qry, function (err, results) {});
} else {
var prefDataJson = utils.safeJSON(results[0].pref_data);
qry =
'UPDATE ' +
crossCtl.db.options.database +
'.tbl_account_users SET bad_pass_count = 0 WHERE auth_type = ' +
type +
' AND auth_key = ' +
mysql.escape(key) +
' AND site_id = ' +
mysql.escape(crossCtl.sConfig.type);
crossCtl.db.doEasyQuery(qry, function (err, results) {});
if (prefDataJson.newAccountFlag === true) {
// console.log('huk new user!!!')
prefDataJson.newAccountFlag = undefined;
var newPrefDataJson = utils.safeJSON(
JSON.stringify(prefDataJson)
);
crossCtl.saveUserPrefData(
results[0].uid,
newPrefDataJson,
function (error, json) {
var user = {
site_id: crossCtl.sConfig.type,
uid: results[0].uid,
name: results[0].name,
auth_flag: true,
user_info: json.account_info,
account_info: results[0],
prefDataJson: json,
newAccountFlag: true,
created: results[0].created,
};
crossCtl.loadProfile(user, cb);
//cb(null, user)
}
);
} else {
var user = {
site_id: crossCtl.sConfig.type,
uid: results[0].uid,
name: results[0].name,
auth_flag: true,
user_info: prefDataJson.account_info,
account_info: results[0],
prefDataJson: prefDataJson,
created: results[0].created,
};
crossCtl.loadProfile(user, cb);
//cb(null, user)
}
// crossCtl.logUserAction(results[0].uid, 'login', 'login ok')
}
}
}
);
}
} else {
// 그냥 업데이트 해 주고 다음으로 이동...
prefDataJson = utils.safeJSON(results[0].pref_data);
if (type == 4) {
info = prefDataJson.account_info;
} else {
prefDataJson.account_info = info;
}
if (token === results[0].auth_token) {
// utils.log('external auth token match!')
} else {
// utils.log('external auth token not match!')
// utils.log('token = ' + token)
// utils.log('results[0].auth_token = ' + results[0].auth_token)
qry =
'UPDATE ' +
crossCtl.db.options.database +
'.tbl_account_users SET auth_token = ' +
mysql.escape(token) +
', pref_data = ' +
mysql.escape(JSON.stringify(prefDataJson)) +
' WHERE serial = ' +
results[0].serial;
crossCtl.db.doEasyQuery(qry, function (err, results) {
if (err) {
utils.log('error', 'doAuth(), update error. ' + err);
}
});
}
var user = {
site_id: crossCtl.sConfig.type,
uid: results[0].uid,
name: results[0].name,
auth_flag: true,
user_info: info,
account_info: results[0],
prefDataJson: prefDataJson,
created: results[0].created,
};
crossCtl.loadProfile(user, cb);
// cb(null, user)
// crossCtl.logUserAction(results[0].uid, 'login', 'login ok')
}
}
}
});
}
passport.use(
new LocalStrategy(passportOptions.local, function (
req,
email,
password,
done
) {
var normalizeUserInfo = crossCtl.normalizeUserInfo('id/password', {
email,
password,
});
console.log('normalizeUserInfo=', normalizeUserInfo);
doAuth(0, email, password, normalizeUserInfo, function (error, user) {
if (error) {
utils.log('error', 'doAuth for local error. ' + error);
}
return done(error, user);
});
})
);
passport.use(
'api-login',
new CustomStrategy(function (req, done) {
if (req.body.info == undefined) {
req.body.info = {};
}
var type = parseInt(req.body.type);
var id = req.body.id;
var token = req.body.token;
var profile =
req.body.info['provider'] != undefined
? req.body.info
: utils.safeJSON(req.body.info);
doAuth(type, id, token, profile, function (error, user) {
if (error) {
utils.log('error', 'doAuth for local error. ' + error);
}
return done(error, user);
});
})
);
var request = require('request');
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
var addRequestId = require('express-request-id')();
app.use(addRequestId);
app.use(function (req, res, next) {
if (req.url !== '/ping') {
req.workTag = utils.getWorkTag(req, res);
req.workTag.responsePacket = {
header: crossCtl.config.header.responseTag,
responseCode: 0,
responseMessage: 'ok',
};
}
next();
});
app.use(function (req, res, next) {
req.uid = req.isAuthenticated()
? req.user.uid
: utils.uuid('uid_' + req.sessionID);
var userNick = '';
var userName = '';
var userEmail = '';
var provider = 'anoymous'; // facebook, google, anoymous
var adminFlag = false;
var profileUrl = '';
var messageCount = 0;
if (req.isAuthenticated() && req.user.auth_flag) {
var params = req.user;
// console.log('req.user=', req.user)
adminFlag = params.account_info.user_level === 5 ? true : false;
if (params.user_info == undefined) {
params.user_info = {};
}
provider = params.user_info.provider
? params.user_info.provider
: 'id/password'; // facebook, google
if (params.user_info.provider === 'facebook') {
userNick = 'f ' + params.user_info.name;
userName = '' + params.user_info.name;
userEmail = '';
} else if (params.user_info.provider === 'google') {
userNick = 'g+ ' + params.account_info.name;
userName = '' + params.account_info.name;
userEmail = params.user_info.email;
profileUrl = params.user_info.photo;
} else if (params.user_info.provider === 'kakao') {
userNick = 'k ' + params.user_info.name;
userName = '' + params.user_info.name;
userEmail = '' + params.user_info.email;
profileUrl = params.user_info.photo;
} else {
userNick = params.user_info.name;
userName = params.user_info.name;
userEmail = params.user_info.name;
}
} else {
userNick = 'anonym';
userName = 'anonym';
userEmail = '';
provider = 'anonymous';
}
var rawLocAry = req.originalUrl.toLowerCase().split('?');
var rawLoc = req.originalUrl.toLowerCase();
var loc = rawLocAry[0];
if (rawLoc.endsWith('/') && rawLoc !== '/') {
rawLoc = rawLoc.substring(0, rawLoc.length - 1);
}
if (loc.endsWith('/') && loc !== '/') {
loc = loc.substring(0, loc.length - 1);
}
var query = req.query;
var finalLang = 'ko';
finalLang = req.session ? (req.session.lang ? req.session.lang : 'ko') : 'ko';
finalLang = req.query.lang ? req.query.lang : finalLang;
var profile = req.isAuthenticated()
? req.user.profile
? req.user.profile
: crossCtl.makeEmptyProfile()
: crossCtl.makeEmptyProfile();
// req.infos.userInfo.userNick
req.infos = {
appInfo: {
name: crossCtl.sConfig.name,
type: crossCtl.sConfig.type,
wsUrl: crossCtl.sConfig.wsUrl,
},
hostName: utils.hostName,
fullUrl:
req.protocol + '://' + req.get('host') + req.originalUrl.toLowerCase(),
rawLoc: rawLoc,
loc: loc,
query: query,
lang: finalLang,
userInfo: {
loginFlag: req.isAuthenticated() && req.user.auth_flag,
userNick: userNick,
userName: profile.display_name,
profileUrl: profile.photo_url,
messageCount: messageCount,
adminFlag: adminFlag,
provider: provider,
fcmTokenFlag: req.session.fcmInfo == undefined ? false : true,
profile: profile,
},
localPath:
'../../../../' + crossCtl.sConfig.type + '/views/' + crossCtl.sConfig.type,
basePath: '../../../../base/views/main',
};
// console.log('req.infos=', req.infos)
// req.setLocale('ko');
// console.log('req.getLocale()=', req.getLocale())
crossCtl.i18n.setLocale(req, finalLang);
var ip = utils.getIPFromReq(req);
// console.log('ip=', ip)
// console.log('req.headers=', req.headers)
if (req.headers['x-forwarded-for']) {
if (req.headers['x-forwarded-by'] === 'bouncy') {
if (req.session) {
req.session.bouncyIP = ip;
}
} else {
if (req.session) {
req.session.bouncyIP = undefined;
}
}
}
/*
if (req.session.bouncyIP !== undefined) {
req.session.bouncyIP = undefined
}
*/
var ip = utils.getIPFromReq(req);
next();
});
app.use(function (req, res, next) {
var err = null;
try {
decodeURIComponent(req.path);
} catch (e) {
err = e;
}
if (err) {
// console.log(err, req.url);
utils.log(
'error',
'URI malformed. url = ' + req.url + ', req = ' + utils.dumpReq(req)
);
if (req.infos.loc.startsWith('/api/')) {
return req.workTag
.res()
.status(500)
.send({
...req.workTag.responsePacket,
responseCode: 500,
responseMessage:
'Server error : URI malformed, make sure that your filename have no % character',
});
} else {
return res.status(404).render('main/pages/next', {
infos: req.infos,
bigTitle: 404,
smallTitle:
'URI malformed, make sure that your filename have no % character',
nextTitle: 'Goto home',
nextUrl: '/',
});
}
}
next();
});
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
// res.header('Access-Control-Allow-Origin', req.headers.origin)
res.header('Access-Control-Allow-Origin', req.headers.origin || '*');
// res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header(
'Access-Control-Allow-Headers',
'Origin, x-api-key, x-access-token, X-Requested-With, X-HTTP-Method-Override, Authorization, Content-Length, Content-Type, Accept, Cache-Control, DomainKey'
);
// intercepts OPTIONS method
if (req.method === 'OPTIONS') {
// respond with 200
res.sendStatus(200);
} else {
// move on
next();
}
});
app.use(function (req, res, next) {
var maintenanceInfo = crossCtl.getMaintenanceInfo();
if (maintenanceInfo !== null) {
var ip = utils.getIPFromReq(req);
if (crossCtl.isItStaffIP(ip)) {
next();
} else {
if (req.infos.loc.startsWith('/api/')) {
req.workTag
.res()
.status(503)
.send({
...req.workTag.responsePacket,
responseCode: 503,
responseMessage: 'Service Temporarily Unavailiable',
});
} else {
res.status(503).render('main/pages/next', {
infos: req.infos,
bigTitle: '점검중',
smallTitle: '준비되는대로 다시 찾아와 주세요.',
nextUrl: 'javascript:alert("꼭이요! ^o^/~")',
nextTitle: '확인',
maintenanceInfo: maintenanceInfo,
});
}
}
} else {
next();
}
});
app.options('/*', function (req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
//res.header("Access-Control-Allow-Origin", req.get("Origin"));
res.header('Access-Control-Allow-Origin', req.get('Origin') || '*');
// res.header("Access-Control-Allow-Origin", req.headers.origin || "*");
// res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header(
'Access-Control-Allow-Headers',
'Origin, x-api-key, x-access-token, X-Requested-With, X-HTTP-Method-Override, Authorization, Content-Length, Content-Type, Accept, Cache-Control, DomainKey'
);
res.send(200);
});
app.use(
'/api/v1',
require('./modules/' + crossCtl.sConfig.type + '/routes/api/v1')
);
app.use(
'/api',
require('./modules/' + crossCtl.sConfig.type + '/routes/api/index')
);
app.use('/api', require('./modules/base/routes/api'));
app.use(
'/admin',
require('./modules/' + crossCtl.sConfig.type + '/routes/admin')
);
app.use('/admin', require('./modules/base/routes/admin'));
app.use('/ck', require('./modules/base/routes/ck'));
app.use('/', require('./modules/base/routes/main'));
app.use('/', require('./modules/' + crossCtl.sConfig.type + '/routes/main'));
// catch 404 and forward to error handler
app.use(function (req, res, next) {
// var err = new Error('Not Found')
// err.status = 404
// next(err)
if (req.infos.loc.startsWith('/api/')) {
req.workTag
.res()
.status(404)
.send({
...req.workTag.responsePacket,
responseCode: 404,
responseMessage: 'api not found',
});
} else {
res.status(404).render('main/pages/next', {
infos: req.infos,
bigTitle: 404,
smallTitle: 'Page not found',
nextTitle: 'Goto home',
nextUrl: '/',
});
}
});
app.use(function (err, req, res, next) {
utils.log('error', 'app trap error ' + err.stack);
utils.log('error', 'exit process after 3 sec ');
crossCtl.boom.flushAll(function (count) {
console.log(count, 'boom flushed...');
setTimeout(function () {
process.exit(1);
}, 1000);
});
});
process.on('uncaughtException', function (err) {
utils.log('error', 'uncaughtException, error ' + err.stack);
utils.log('error', 'exit process after 3 sec ');
crossCtl.boom.flushAll(function (count) {
console.log(count, 'boom flushed...');
setTimeout(function () {
process.exit(1);
}, 1000);
});
});
process.on('SIGINT', function () {
console.log('Caught interrupt signal');
utils.log('error', 'exit process after 3 sec ');
crossCtl.boom.flushAll(function (count) {
console.log(count, 'boom flushed...');
setTimeout(function () {
process.exit(1);
}, 1000);
});
});
process.on('SIGTERM', function () {
console.log('Caught term signal');
utils.log('error', 'exit process after 3 sec ');
crossCtl.boom.flushAll(function (count) {
console.log(count, 'boom flushed...');
setTimeout(function () {
process.exit(1);
}, 1000);
});
});
// error handler
/*
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message
res.locals.error = req.app.get('env') === 'development' ? err : {}
// render the error page
res.status(err.status || 500)
res.render('error')
})
*/
module.exports = app;