getpgdata: главная отдаёт info напрямую (без EJS), версия 1.0.2
This commit is contained in:
@@ -90,3 +90,29 @@ getpgdata/
|
||||
- `package-lock.json` закоммичен (зависимости: express, ejs, pg).
|
||||
- `node_modules/` в `.gitignore`.
|
||||
- Версия в `package.json` повышается при каждой правке кода (правило проекта).
|
||||
|
||||
## 6. Минимальный вывод на экран (фикс падения пода)
|
||||
|
||||
Несмотря на фикс порта (п.4), деплой снова упал — под `nodejsk8s` не поднялся.
|
||||
|
||||
**Требование пользователя:** «сделай код минимальным. Сам код не удаляй — сделай вывод
|
||||
на экран какой-то информации и всё».
|
||||
|
||||
**Решение (коммит c8a776e, версия 1.0.2):**
|
||||
- Роут `GET /` переписан так, чтобы **не зависеть от EJS-шаблонов**: отдаёт простой HTML
|
||||
напрямую (`res.send`), выводя:
|
||||
- версию Node, `APP_ENV`, PID
|
||||
- конфиг БД (host, port, database, user)
|
||||
- статус подключения к БД (или текст ошибки)
|
||||
- список таблиц (или сообщение об ошибке)
|
||||
- Каждая попытка работы с БД обёрнута в try/catch, поэтому страница **всегда** отдаёт 200
|
||||
с информацией, даже если БД недоступна.
|
||||
- Весь остальной код (роуты `/table`, `/query`, `/healthz`, `dbConfig`, `pool`) **не удалён** —
|
||||
только главная страница упрощена.
|
||||
|
||||
**Проверено:** синтаксис OK; запуск без env `PORT` → слушает `0.0.0.0:3000`;
|
||||
`GET /` → 200 (HTML с конфигом и статусом БД), `GET /healthz` при недоступной БД → 503 degraded.
|
||||
|
||||
**⚠️ Точная причина падения пода по-прежнему не подтверждена** (нет доступа к логам Nubes).
|
||||
Если под не поднимется и после этого — смотреть логи `nodejsk8s` Deployment в Nubes UI:
|
||||
replica не активна (CrashLoopBackOff, invalidImage, порт/health, зависший старт).
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "getpgdata",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.2",
|
||||
"description": "Node.js приложение для доступа к PostgreSQL (managed k8s, internal-only)",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -62,31 +62,80 @@ app.get('/healthz', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Главная: состояние подключения + список таблиц
|
||||
// Главная: минимальный вывод информации на экран.
|
||||
// Не зависит от EJS-шаблонов — всегда отдаёт HTML, даже если БД недоступна.
|
||||
app.get('/', async (req, res) => {
|
||||
let tables = null;
|
||||
let error = null;
|
||||
const cfg = dbConfig();
|
||||
|
||||
let dbStatus = 'нет данных';
|
||||
let tablesHtml = '';
|
||||
|
||||
try {
|
||||
const r = await pool.query(
|
||||
const r = await pool.query('SELECT version() AS v');
|
||||
dbStatus = 'подключено: ' + (r.rows[0] && r.rows[0].v ? r.rows[0].v : 'ok');
|
||||
} catch (e) {
|
||||
dbStatus = 'недоступна: ' + (e && e.message ? e.message : String(e));
|
||||
}
|
||||
|
||||
try {
|
||||
const t = await pool.query(
|
||||
`SELECT schemaname, tablename
|
||||
FROM pg_tables
|
||||
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
|
||||
ORDER BY schemaname, tablename`
|
||||
);
|
||||
tables = r.rows;
|
||||
if (t.rows && t.rows.length) {
|
||||
tablesHtml = t.rows
|
||||
.map((r) => `<tr><td>${esc(r.schemaname)}</td><td>${esc(r.tablename)}</td></tr>`)
|
||||
.join('');
|
||||
} else {
|
||||
tablesHtml = '<tr><td colspan="2">таблиц нет</td></tr>';
|
||||
}
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
tablesHtml = '<tr><td colspan="2">не удалось получить таблицы</td></tr>';
|
||||
}
|
||||
|
||||
res.render('index', {
|
||||
cfg: dbConfig(),
|
||||
tables,
|
||||
error,
|
||||
env: APP_ENV,
|
||||
});
|
||||
res
|
||||
.status(200)
|
||||
.set('Content-Type', 'text/html; charset=utf-8')
|
||||
.send(html(cfg, dbStatus, tablesHtml));
|
||||
});
|
||||
|
||||
// Экранирование HTML
|
||||
function esc(v) {
|
||||
return String(v).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
}
|
||||
|
||||
// Простая HTML-страница с информацией
|
||||
function html(cfg, dbStatus, tablesHtml) {
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>getpgdata — информация</title>
|
||||
</head>
|
||||
<body style="font-family: sans-serif; margin: 24px;">
|
||||
<h1>getpgdata</h1>
|
||||
<p>Node.js ${esc(process.version)} · env=${esc(APP_ENV)} · PID=${esc(String(process.pid))}</p>
|
||||
|
||||
<h2>База данных</h2>
|
||||
<table border="1" cellspacing="0" cellpadding="6">
|
||||
<tr><th>Host</th><td>${esc(cfg.host)}</td></tr>
|
||||
<tr><th>Port</th><td>${esc(String(cfg.port))}</td></tr>
|
||||
<tr><th>Database</th><td>${esc(cfg.database)}</td></tr>
|
||||
<tr><th>User</th><td>${esc(cfg.user)}</td></tr>
|
||||
<tr><th>Статус</th><td>${esc(dbStatus)}</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>Таблицы</h2>
|
||||
<table border="1" cellspacing="0" cellpadding="6">
|
||||
<tr><th>Схема</th><th>Таблица</th></tr>
|
||||
${tablesHtml}
|
||||
</table>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
// Просмотр таблицы с пагинацией
|
||||
app.get('/table', async (req, res) => {
|
||||
const schema = (req.query.schema || 'public').replace(/[^a-zA-Z0-9_]/g, '');
|
||||
|
||||
Reference in New Issue
Block a user