refactor: split GitOps renderer by responsibility
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
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
|
||||
Reference in New Issue
Block a user