Files
pikasTech-HWLAB/scripts/src/gitops-render/templates/dependency-proxy-probe.sh
T

96 lines
3.0 KiB
Bash

HWLAB_PROXY_PROBE_PHASE=__HWLAB_PROXY_PHASE_SHELL__ HWLAB_PROXY_PROBE_URL=__HWLAB_PROXY_TARGET_SHELL__ node <<'NODE' || echo '{"event":"dependency-proxy-probe-nonblocking","phase":"__HWLAB_PROXY_PHASE__","ok":false,"reason":"probe-failed-but-continuing"}'
const net = require("node:net");
const phase = process.env.HWLAB_PROXY_PROBE_PHASE || "unknown";
const target = new URL(process.env.HWLAB_PROXY_PROBE_URL || "http://deb.debian.org/debian/dists/bookworm/InRelease");
const proxyRaw = process.env.HTTP_PROXY || process.env.http_proxy || "";
function redactProxy(value) {
if (!value) return "";
try {
const parsed = new URL(value);
if (parsed.username || parsed.password) {
parsed.username = "***";
parsed.password = "";
}
return parsed.toString();
} catch {
return "<invalid-proxy-url>";
}
}
function emit(payload, exitCode = 0) {
console.log(JSON.stringify({
event: "dependency-proxy-probe",
phase,
target: target.href,
proxy: redactProxy(proxyRaw),
...payload
}));
if (exitCode) process.exit(exitCode);
}
if (!proxyRaw) emit({ ok: false, reason: "proxy-env-missing" }, 21);
let proxy;
try {
proxy = new URL(proxyRaw);
} catch (error) {
emit({ ok: false, reason: "proxy-url-invalid", error: error.message }, 22);
}
if (proxy.protocol !== "http:" && proxy.protocol !== "https:") {
emit({ ok: false, reason: "http-proxy-required", protocol: proxy.protocol }, 23);
}
const startedAt = Date.now();
const socket = net.createConnection({ host: proxy.hostname, port: Number(proxy.port || (proxy.protocol === "https:" ? 443 : 80)) });
let bytes = 0;
let firstByteMs = null;
let responseHead = "";
let finished = false;
const timeout = setTimeout(() => {
if (finished) return;
finished = true;
socket.destroy();
emit({ ok: false, reason: "timeout", timeoutMs: 15000 }, 24);
}, 15000);
socket.on("connect", () => {
socket.write("GET " + target.href + " HTTP/1.1\r\nHost: " + target.host + "\r\nUser-Agent: hwlab-node-proxy-probe\r\nConnection: close\r\n\r\n");
});
socket.on("data", (chunk) => {
if (firstByteMs === null) firstByteMs = Date.now() - startedAt;
bytes += chunk.length;
if (responseHead.length < 240) responseHead += chunk.toString("utf8", 0, Math.min(chunk.length, 240 - responseHead.length));
});
socket.on("end", () => {
if (finished) return;
finished = true;
clearTimeout(timeout);
const totalMs = Date.now() - startedAt;
const statusLine = responseHead.split("\r\n", 1)[0] || "";
const statusCode = Number(statusLine.split(" ")[1] || 0);
const ok = statusLine.startsWith("HTTP/") && statusCode >= 200 && statusCode < 400;
emit({
ok,
reason: ok ? null : "bad-http-status",
statusLine,
statusCode,
firstByteMs,
totalMs,
bytes,
speedBytesPerSecond: totalMs > 0 ? Math.round(bytes * 1000 / totalMs) : 0
}, ok ? 0 : 25);
});
socket.on("error", (error) => {
if (finished) return;
finished = true;
clearTimeout(timeout);
emit({ ok: false, reason: "proxy-connect-failed", error: error.message, totalMs: Date.now() - startedAt }, 26);
});
NODE