diff --git a/renderer/README.md b/renderer/README.md index 2f0b807..bb25521 100644 --- a/renderer/README.md +++ b/renderer/README.md @@ -21,7 +21,7 @@ signed off) and the public **legal pages** (the offer, the privacy policy and th here; a backend outage yields a 502, never a stale price list. - `GET /privacy/` — the privacy policy, and `GET /eula/` the end-user licence agreement, both as `text/html`: the owner-edited `ui/legal/privacy_ru.md` / `ui/legal/eula_ru.md` (baked in, read at - boot), rendered by the same shared `renderLegalHtml`. **Static** — no backend fetch. `GET /privacy` + boot), rendered once at boot by the same shared `renderLegalHtml` and served from cache. **Static** — no backend fetch. `GET /privacy` / `GET /eula` → 301 to the trailing-slash form. Caddy routes these here too. - `GET /healthz` — liveness (the compose healthcheck the backend's `depends_on` gates on). diff --git a/renderer/src/server.mjs b/renderer/src/server.mjs index 2a819a5..bd1b3e5 100644 --- a/renderer/src/server.mjs +++ b/renderer/src/server.mjs @@ -33,6 +33,12 @@ const OFFER_MD = readFileSync(process.env.RENDERER_OFFER_MD || new URL('../legal // boot, no dynamic data. RENDERER_PRIVACY_MD / RENDERER_EULA_MD override the baked path for a local run. const PRIVACY_MD = readFileSync(process.env.RENDERER_PRIVACY_MD || new URL('../legal/privacy_ru.md', import.meta.url), 'utf8'); const EULA_MD = readFileSync(process.env.RENDERER_EULA_MD || new URL('../legal/eula_ru.md', import.meta.url), 'utf8'); +// Render the static legal pages once at boot and serve the cached HTML: they carry no dynamic data, +// and re-parsing the large EULA markdown on every request is slow enough under deploy-time host +// contention (the renderer is CPU/memory-capped) to flake the contour probe. The offer stays +// per-request because it splices in the live price list. +const PRIVACY_HTML = renderPrivacy(PRIVACY_MD); +const EULA_HTML = renderEula(EULA_MD); const OFFER_PRICING_URL = (process.env.RENDERER_BACKEND_URL || 'http://backend:8080') + '/api/v1/internal/offer/pricing'; @@ -89,13 +95,13 @@ const server = createServer(async (req, res) => { if (req.method === 'GET' && path === '/privacy/') { res .writeHead(200, { 'content-type': 'text/html; charset=utf-8', 'cache-control': 'no-cache' }) - .end(renderPrivacy(PRIVACY_MD)); + .end(PRIVACY_HTML); return; } if (req.method === 'GET' && path === '/eula/') { res .writeHead(200, { 'content-type': 'text/html; charset=utf-8', 'cache-control': 'no-cache' }) - .end(renderEula(EULA_MD)); + .end(EULA_HTML); return; } if (req.method === 'POST' && path === '/render') {