Fix: убран process.exit(1) — приложение не падает, показывает сообщение об ошибке. Версия 0.1.14

This commit is contained in:
2026-07-08 21:20:43 +04:00
parent 771473c97a
commit 1b902c5540
3 changed files with 32 additions and 26 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "ipwhitelist",
"version": "0.1.13",
"version": "0.1.14",
"description": "IP WhiteList microservice for cloud provider",
"main": "server.js",
"scripts": {
+30 -24
View File
@@ -61,23 +61,16 @@ async function start() {
const { pool } = require('./src/db');
app.use(createSessionMiddleware(pool));
// ── Fail-fast в production ────────────────────────────────────────────────
// Если секреты не заданы — приложение в проде немедленно падает.
// Дефолтные значения — только для локальной разработки.
// ── Fail-fast в production (без exit — сообщение в лог) ────────────────────
const DEFAULT_SESSION = 'dev-session-secret-change-me';
let fatalError = null;
if (process.env.NODE_ENV === 'production') {
const DEFAULT_SESSION = 'dev-session-secret-change-me';
if (!process.env.SESSION_SECRET || process.env.SESSION_SECRET === DEFAULT_SESSION) {
console.error('FATAL: SESSION_SECRET не задан или равен дефолту в production!');
process.exit(1);
}
if (!process.env.DB_PASS) {
console.error('FATAL: DB_PASS не задан в production!');
process.exit(1);
}
if (!process.env.CSRF_SECRET || process.env.CSRF_SECRET === 'dev-csrf-secret-change-in-prod') {
console.error('FATAL: CSRF_SECRET не задан или равен дефолту в production!');
process.exit(1);
}
if (!process.env.SESSION_SECRET || process.env.SESSION_SECRET === DEFAULT_SESSION)
fatalError = 'SESSION_SECRET не задан или равен дефолту в production';
else if (!process.env.DB_PASS)
fatalError = 'DB_PASS не задан в production';
else if (!process.env.CSRF_SECRET || process.env.CSRF_SECRET === 'dev-csrf-secret-change-in-prod')
fatalError = 'CSRF_SECRET не задан или равен дефолту в production';
}
// k8s liveness + readiness probes
@@ -91,6 +84,15 @@ async function start() {
}
});
// Если фатальная ошибка конфигурации — показываем на всех страницах сообщение
if (fatalError) {
console.error(fatalError);
app.use((req, res) => {
res.status(503).type('html').send(errorPage(fatalError));
});
return app;
}
// JWKS endpoint для валидации токенов внешними сервисами (только в mock-режиме)
if (auth.jwksHandler) app.get('/.well-known/jwks.json', auth.jwksHandler);
@@ -136,20 +138,24 @@ async function start() {
if (require.main === module) {
start()
.then(a => {
const server = a.listen(PORT, () => console.log('Server on port ' + PORT));
a.listen(PORT, () => console.log('Server on port ' + PORT));
// Graceful shutdown по SIGTERM (k8s)
process.on('SIGTERM', () => {
console.log('SIGTERM — shutting down...');
server.close(() => {
console.log('HTTP closed');
const { pool } = require('./src/db');
pool.end().then(() => { console.log('DB pool closed'); process.exit(0); });
});
const { pool } = require('./src/db');
pool.end().then(() => { console.log('DB pool closed'); process.exit(0); });
setTimeout(() => { console.log('Forced exit'); process.exit(0); }, 10000);
});
return server;
})
.catch(e => { console.error('Startup error:', e); process.exit(1); });
.catch(e => {
console.error('Startup error:', e.message);
// Не падаем — запускаем HTTP с сообщением об ошибке
const errorApp = require('express')();
errorApp.use((req, res) => {
res.status(503).type('html').send('<html><head><meta charset="utf-8"><title>Авария</title></head><body style="font-family:sans-serif;padding:40px;text-align:center"><h1>⚙️ Сервис временно недоступен</h1><p>Причина: ' + (e.message || 'неизвестна') + '</p><p>Попробуйте обновить страницу через минуту</p></body></html>');
});
errorApp.listen(PORT, () => console.log('Server on port ' + PORT + ' (ERROR MODE)'));
});
}
module.exports = { start };
+1 -1
View File
@@ -8,7 +8,7 @@
// ═══════════════════════════════════════════════════════════════════════════════
module.exports = {
version: '0.1.13',
version: '0.1.14',
// ── Среда ─────────────────────────────────────────────────────────────────
// APP_ENV=test → тестовый стенд (жёлтый баннер в UI, можно включать тестовый API)