From a0380b3f660127c9be81c46b30b812ac95cb07ee Mon Sep 17 00:00:00 2001 From: Denozordec Date: Fri, 26 Jun 2026 00:15:22 +0700 Subject: [PATCH] chore: Add undici package and update health check service to utilize undici's Agent for improved HTTP probing --- apps/api/package.json | 1 + apps/api/src/services/health-check-service.ts | 22 ++++++++++++++++++- pnpm-lock.yaml | 9 ++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/apps/api/package.json b/apps/api/package.json index 46fb0d1..b2d331c 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -26,6 +26,7 @@ "p-limit": "^6.2.0", "p-queue": "^8.1.0", "toad-scheduler": "^4.0.1", + "undici": "^8.5.0", "zod": "^4.2.0" }, "devDependencies": { diff --git a/apps/api/src/services/health-check-service.ts b/apps/api/src/services/health-check-service.ts index 1f739e0..7a6dddf 100644 --- a/apps/api/src/services/health-check-service.ts +++ b/apps/api/src/services/health-check-service.ts @@ -1,4 +1,5 @@ import { connect } from "node:net"; +import { Agent } from "undici"; import type { Db } from "@cfdm/db"; import { repos } from "@cfdm/db"; import type { HealthCheckTarget, IpHealthState } from "@cfdm/shared"; @@ -64,14 +65,33 @@ async function httpProbe( ): Promise { const started = Date.now(); const path = target.path?.trim() || "/"; - const url = `http://${ip}${path.startsWith("/") ? path : `/${path}`}`; + const pathWithSlash = path.startsWith("/") ? path : `/${path}`; + const port = target.port ?? 80; const hostHeader = target.hostname || ip; + const useTls = port === 443; + // For HTTPS probing against a raw IP, set SNI/Host so TLS handshake and vhost routing work. + const authorityHost = target.hostname || ip; + const url = useTls + ? `https://${authorityHost}${pathWithSlash}` + : `http://${ip}${pathWithSlash}`; + // Custom dispatcher for HTTPS-to-IP: connect to the literal IP, but present hostname via SNI. + const dispatcher = + useTls && target.hostname + ? new Agent({ + connect: { + servername: target.hostname, + rejectUnauthorized: false, + }, + }) + : undefined; try { const response = await fetch(url, { method: "GET", headers: { Host: hostHeader }, signal: AbortSignal.timeout(timeoutMs), redirect: "manual", + // @ts-expect-error undici dispatcher option is not in fetch types + dispatcher, }); const latency = Date.now() - started; if (target.expected_status != null) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 528dc01..897c371 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -66,6 +66,9 @@ importers: toad-scheduler: specifier: ^4.0.1 version: 4.0.1 + undici: + specifier: ^8.5.0 + version: 8.5.0 zod: specifier: ^4.2.0 version: 4.4.3 @@ -3763,6 +3766,10 @@ packages: undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + undici@8.5.0: + resolution: {integrity: sha512-xamtWoB1EshgjpmlXd7GGm2VfdDtw1+rD8uhry8pSNW3If6S8E0m2T2+orSKeZXEn/aPJMviCpDBA65WJt8zhg==} + engines: {node: '>=22.19.0'} + unplugin@3.0.0: resolution: {integrity: sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7095,6 +7102,8 @@ snapshots: undici-types@7.18.2: {} + undici@8.5.0: {} + unplugin@3.0.0: dependencies: '@jridgewell/remapping': 2.3.5