refactor: Update health check service to use undici's fetch for improved HTTP probing and enhance FormFieldSimple component with optional hint prop
Build, Test, and Push CFDM Docker Image / test (push) Successful in 4m4s
Build, Test, and Push CFDM Docker Image / build-and-push (push) Successful in 2m25s
Build, Test, and Push CFDM Docker Image / update-wiki (push) Successful in 7s
Build, Test, and Push CFDM Docker Image / create-release (push) Has been skipped

This commit is contained in:
Denozordec
2026-06-26 00:30:51 +07:00
parent a0380b3f66
commit 6038feda66
3 changed files with 16 additions and 12 deletions
+9 -11
View File
@@ -1,5 +1,5 @@
import { connect } from "node:net"; import { connect } from "node:net";
import { Agent } from "undici"; import { Agent, fetch as undiciFetch } from "undici";
import type { Db } from "@cfdm/db"; import type { Db } from "@cfdm/db";
import { repos } from "@cfdm/db"; import { repos } from "@cfdm/db";
import type { HealthCheckTarget, IpHealthState } from "@cfdm/shared"; import type { HealthCheckTarget, IpHealthState } from "@cfdm/shared";
@@ -67,14 +67,13 @@ async function httpProbe(
const path = target.path?.trim() || "/"; const path = target.path?.trim() || "/";
const pathWithSlash = path.startsWith("/") ? path : `/${path}`; const pathWithSlash = path.startsWith("/") ? path : `/${path}`;
const port = target.port ?? 80; const port = target.port ?? 80;
const hostHeader = target.hostname || ip;
const useTls = port === 443; const useTls = port === 443;
// For HTTPS probing against a raw IP, set SNI/Host so TLS handshake and vhost routing work. // For HTTPS on 443, probe via the hostname (URL host = hostname) so TLS SNI, Host header
const authorityHost = target.hostname || ip; // and any edge/vhost protection (e.g. Cloudflare origin 421 on direct-IP) all line up.
const url = useTls // For multi-A records this loses strict per-IP HTTPS granularity — use TCP probe for that.
? `https://${authorityHost}${pathWithSlash}` // For plain HTTP we still hit the literal IP (per-record target).
: `http://${ip}${pathWithSlash}`; const urlHost = useTls ? target.hostname || ip : ip;
// Custom dispatcher for HTTPS-to-IP: connect to the literal IP, but present hostname via SNI. const url = `${useTls ? "https" : "http"}://${urlHost}${pathWithSlash}`;
const dispatcher = const dispatcher =
useTls && target.hostname useTls && target.hostname
? new Agent({ ? new Agent({
@@ -85,12 +84,11 @@ async function httpProbe(
}) })
: undefined; : undefined;
try { try {
const response = await fetch(url, { const response = await undiciFetch(url, {
method: "GET", method: "GET",
headers: { Host: hostHeader }, headers: { Host: target.hostname || ip },
signal: AbortSignal.timeout(timeoutMs), signal: AbortSignal.timeout(timeoutMs),
redirect: "manual", redirect: "manual",
// @ts-expect-error undici dispatcher option is not in fetch types
dispatcher, dispatcher,
}); });
const latency = Date.now() - started; const latency = Date.now() - started;
+5
View File
@@ -63,6 +63,7 @@ interface FormFieldSimpleProps {
label: string label: string
htmlFor: string htmlFor: string
error?: { message?: string } error?: { message?: string }
hint?: string
className?: string className?: string
children: ReactNode children: ReactNode
} }
@@ -71,6 +72,7 @@ export function FormFieldSimple({
label, label,
htmlFor, htmlFor,
error, error,
hint,
className, className,
children, children,
}: FormFieldSimpleProps) { }: FormFieldSimpleProps) {
@@ -78,6 +80,9 @@ export function FormFieldSimple({
<Field data-invalid={!!error} className={cn(className)}> <Field data-invalid={!!error} className={cn(className)}>
<FieldLabel htmlFor={htmlFor}>{label}</FieldLabel> <FieldLabel htmlFor={htmlFor}>{label}</FieldLabel>
{children} {children}
{hint && !error && (
<p className="text-xs text-muted-foreground">{hint}</p>
)}
<FieldError errors={[error]} /> <FieldError errors={[error]} />
</Field> </Field>
) )
@@ -141,10 +141,11 @@ export function HealthCheckConfigFields({
<FormFieldSimple <FormFieldSimple
label="HTTP path" label="HTTP path"
htmlFor={`${idPrefix}-path`} htmlFor={`${idPrefix}-path`}
hint="Опционально. По умолчанию проверяется /"
> >
<AppInput <AppInput
id={`${idPrefix}-path`} id={`${idPrefix}-path`}
placeholder="/health" placeholder="/"
value={value.path ?? ''} value={value.path ?? ''}
onChange={(e) => onChange={(e) =>
patch({ path: e.target.value === '' ? null : e.target.value }) patch({ path: e.target.value === '' ? null : e.target.value })