diff --git a/DOCKER.md b/DOCKER.md index edb9954..3916fcf 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -110,6 +110,26 @@ docker-compose up -d | `EVOBGP_API_URL` | Базовый URL API EvoBGP для серверного прокси `/api/evobgp` (например `http://evobgp:8080` или `http://10.0.0.5:8080`; при необходимости к пути добавляется `/v1`) | - | Да, если используете интеграцию EvoBGP в UI | | `EVOBGP_API_TOKEN` | Bearer-токен к API EvoBGP (только на сервере, не в браузере) | - | Да, если используете интеграцию EvoBGP в UI | +### EvoBGP и reverse proxy (nginx) + +Запросы UI идут на тот же origin: `/api/evobgp/…` обрабатывает **Node** внутри образа. Если перед приложением стоит **nginx**, нужно проксировать префикс `/api` на Node **без потери** сегмента `/api` в URI (иначе в upstream попадёт не тот путь и будет 404). + +**Рекомендуемый вариант** (путь `/api/…` сохраняется): + +```nginx +location /api/ { + proxy_pass http://127.0.0.1:3001/api/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; +} +``` + +**Типичная ошибка**: внутри `location /api` указать `proxy_pass http://127.0.0.1:3001/;` — nginx **срезает** `/api`, в Node приходит `/evobgp/router-lists/catalog` вместо `/api/evobgp/router-lists/catalog`. В коде добавлен запасной маршрут на `/evobgp`, но лучше поправить nginx. + +**Проверка**: `GET http://<хост>:<порт>/api/evobgp` (без хвоста) должен вернуть JSON вида `{"ok":true,"proxy":true,"evobgpConfigured":true}` — если вместо этого HTML «404» или страница SPA, запрос **не доходит** до Node (только статика, другой порт или неверный `proxy_pass`). + ### ENCRYPTION_KEY **Важно**: `ENCRYPTION_KEY` является обязательным параметром для работы с IPSec паролями. Этот ключ используется для шифрования/дешифрования паролей, хранящихся в S3. diff --git a/backend/server.js b/backend/server.js index e944c56..ddb1357 100644 --- a/backend/server.js +++ b/backend/server.js @@ -38,7 +38,7 @@ const { initNetworkMapScheduler } = require('./services/networkMapScheduler'); const { initPingServicesScheduler } = require('./services/pingServicesScheduler'); const { initUptimeMonitorScheduler } = require('./services/uptimeMonitorScheduler'); const schedulerRoutes = require('./routes/schedulerRoutes'); -const { createEvobgpProxy } = require('./routes/evobgpProxyRoutes'); +const { createEvobgpProxy, normalizeEvobgpBaseUrl } = require('./routes/evobgpProxyRoutes'); const app = express(); const port = Number(process.env.PORT) || 3001; @@ -158,7 +158,21 @@ app.get('/api/version', (req, res) => { }); // === EvoBGP reverse proxy (токен и URL только на сервере; без CORS в браузере) === +function evobgpProxyHealth(req, res) { + const base = normalizeEvobgpBaseUrl(process.env.EVOBGP_API_URL || ''); + const hasToken = Boolean(String(process.env.EVOBGP_API_TOKEN || '').trim()); + res.json({ + ok: true, + proxy: true, + evobgpConfigured: Boolean(base && hasToken), + }); +} +// Точное совпадение до app.use: GET /api/evobgp и GET /evobgp — проверка, что запрос доходит до Node +app.get('/api/evobgp', evobgpProxyHealth); +app.get('/evobgp', evobgpProxyHealth); app.use('/api/evobgp', createEvobgpProxy({ logger })); +// Если nginx делает proxy_pass http://upstream/ и срезает префикс /api, до приложения приходит /evobgp/… +app.use('/evobgp', createEvobgpProxy({ logger })); // === Cache TTL === const DEFAULT_CACHE_TTL = Math.max(0, Math.min(300, Number(process.env.CACHE_TTL_SECONDS) || 30));