getpgdata: главная отдаёт info напрямую (без EJS), версия 1.0.2
This commit is contained in:
@@ -90,3 +90,29 @@ getpgdata/
|
|||||||
- `package-lock.json` закоммичен (зависимости: express, ejs, pg).
|
- `package-lock.json` закоммичен (зависимости: express, ejs, pg).
|
||||||
- `node_modules/` в `.gitignore`.
|
- `node_modules/` в `.gitignore`.
|
||||||
- Версия в `package.json` повышается при каждой правке кода (правило проекта).
|
- Версия в `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",
|
"name": "getpgdata",
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"description": "Node.js приложение для доступа к PostgreSQL (managed k8s, internal-only)",
|
"description": "Node.js приложение для доступа к PostgreSQL (managed k8s, internal-only)",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -62,31 +62,80 @@ app.get('/healthz', async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Главная: состояние подключения + список таблиц
|
// Главная: минимальный вывод информации на экран.
|
||||||
|
// Не зависит от EJS-шаблонов — всегда отдаёт HTML, даже если БД недоступна.
|
||||||
app.get('/', async (req, res) => {
|
app.get('/', async (req, res) => {
|
||||||
let tables = null;
|
const cfg = dbConfig();
|
||||||
let error = null;
|
|
||||||
|
let dbStatus = 'нет данных';
|
||||||
|
let tablesHtml = '';
|
||||||
|
|
||||||
try {
|
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
|
`SELECT schemaname, tablename
|
||||||
FROM pg_tables
|
FROM pg_tables
|
||||||
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
|
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
|
||||||
ORDER BY schemaname, tablename`
|
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) {
|
} catch (e) {
|
||||||
error = e.message;
|
tablesHtml = '<tr><td colspan="2">не удалось получить таблицы</td></tr>';
|
||||||
}
|
}
|
||||||
|
|
||||||
res.render('index', {
|
res
|
||||||
cfg: dbConfig(),
|
.status(200)
|
||||||
tables,
|
.set('Content-Type', 'text/html; charset=utf-8')
|
||||||
error,
|
.send(html(cfg, dbStatus, tablesHtml));
|
||||||
env: APP_ENV,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Экранирование 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) => {
|
app.get('/table', async (req, res) => {
|
||||||
const schema = (req.query.schema || 'public').replace(/[^a-zA-Z0-9_]/g, '');
|
const schema = (req.query.schema || 'public').replace(/[^a-zA-Z0-9_]/g, '');
|
||||||
|
|||||||
Reference in New Issue
Block a user