From 73afce35bdc6110f707c8f7eca43d252ae4519f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Mon, 22 Jun 2026 20:02:01 +0400 Subject: [PATCH] v0.5.178: graceful shutdown, CSRF_SECRET fail-fast, /ready probe --- package.json | 2 +- server.js | 29 +++++++++++++++++++++++++++-- v2/src/config/index.js | 2 +- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index db527dc..98a9e8c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipwhitelist", - "version": "0.5.177", + "version": "0.5.178", "description": "IP WhiteList microservice for cloud provider", "main": "server.js", "scripts": { diff --git a/server.js b/server.js index 62f97c3..a4b1d2b 100644 --- a/server.js +++ b/server.js @@ -74,10 +74,22 @@ async function start() { 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); + } } - // k8s liveness probe — простая проверка что сервер жив + // k8s liveness + readiness probes app.get('/healthz', (req, res) => res.send('OK')); + app.get('/ready', async (req, res) => { + try { + await pool.query('SELECT 1'); + res.send('OK'); + } catch (e) { + res.status(503).send('DB not ready'); + } + }); // JWKS endpoint для валидации токенов внешними сервисами (только в mock-режиме) if (auth.jwksHandler) app.get('/.well-known/jwks.json', auth.jwksHandler); @@ -123,7 +135,20 @@ async function start() { // Запускаем сервер только если файл запущен напрямую (не через require) if (require.main === module) { start() - .then(a => a.listen(PORT, () => console.log('Server on port ' + PORT))) + .then(a => { + const server = 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); }); + }); + setTimeout(() => { console.log('Forced exit'); process.exit(0); }, 10000); + }); + return server; + }) .catch(e => { console.error('Startup error:', e); process.exit(1); }); } diff --git a/v2/src/config/index.js b/v2/src/config/index.js index 8787a30..e097ab7 100644 --- a/v2/src/config/index.js +++ b/v2/src/config/index.js @@ -8,7 +8,7 @@ // ═══════════════════════════════════════════════════════════════════════════════ module.exports = { - version: '0.5.177', + version: '0.5.178', // ── IAM ────────────────────────────────────────────────────────────────── iamUrl: process.env.V2_IAM_URL || 'https://auth-api.ngcloud.ru/api/v1/auth/user',