Refactor VPN proxy client implementation
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
renderPrometheusMetrics,
|
||||
sendPrometheusMetrics,
|
||||
} from '../../src/server/prometheusMetrics.js';
|
||||
} from '../../dist/server/prometheusMetrics.js';
|
||||
import { createPrometheusMetricsRoute } from '../../dist/server/http/routes/prometheusMetricsRoute.js';
|
||||
|
||||
const observedAt = '2026-08-08T10:00:00.000Z';
|
||||
const snapshot = {
|
||||
@@ -98,3 +100,97 @@ test('invalid canonical counters fail the scrape instead of publishing corrupt v
|
||||
/Invalid Prometheus counter/,
|
||||
);
|
||||
});
|
||||
|
||||
function routeResponse() {
|
||||
return {
|
||||
writeHead(status, headers) {
|
||||
this.status = status;
|
||||
this.headers = headers;
|
||||
},
|
||||
end(body) {
|
||||
this.body = body;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test('Prometheus route reads one current snapshot and preserves the exact text contract', async () => {
|
||||
let reads = 0;
|
||||
let refreshes = 0;
|
||||
const route = createPrometheusMetricsRoute({
|
||||
deviceInventory: {
|
||||
metricsSnapshot: () => {
|
||||
reads += 1;
|
||||
return snapshot;
|
||||
},
|
||||
refresh: () => { refreshes += 1; },
|
||||
},
|
||||
});
|
||||
const res = routeResponse();
|
||||
assert.equal(await route.handle({ method: 'GET', url: '/metrics?source=prometheus' }, res), true);
|
||||
assert.equal(reads, 1);
|
||||
assert.equal(refreshes, 0);
|
||||
assert.equal(res.status, 200);
|
||||
assert.equal(res.headers['content-type'], 'text/plain; version=0.0.4; charset=utf-8');
|
||||
assert.equal(res.body, renderPrometheusMetrics(snapshot));
|
||||
assert.equal(res.body.endsWith('\n'), true);
|
||||
});
|
||||
|
||||
test('Prometheus route preserves path, method and nullable inventory gating', async () => {
|
||||
let reads = 0;
|
||||
const route = createPrometheusMetricsRoute({
|
||||
deviceInventory: { metricsSnapshot: () => { reads += 1; return snapshot; } },
|
||||
});
|
||||
for (const url of ['/metrics/', '/api/metrics', '/']) {
|
||||
assert.equal(await route.handle({ method: 'GET', url }, routeResponse()), false);
|
||||
}
|
||||
await assert.rejects(
|
||||
route.handle({ method: 'POST', url: '/metrics' }, routeResponse()),
|
||||
(error) => error.code === 'ENDPOINT_NOT_FOUND',
|
||||
);
|
||||
assert.equal(reads, 0);
|
||||
|
||||
const clientRoute = createPrometheusMetricsRoute({ deviceInventory: null });
|
||||
await assert.rejects(
|
||||
clientRoute.handle({ method: 'GET', url: '/metrics' }, routeResponse()),
|
||||
(error) => error.code === 'ENDPOINT_NOT_FOUND',
|
||||
);
|
||||
});
|
||||
|
||||
test('Prometheus route propagates snapshot and renderer failures unchanged', async () => {
|
||||
const snapshotError = new Error('snapshot failed');
|
||||
const snapshotRoute = createPrometheusMetricsRoute({
|
||||
deviceInventory: { metricsSnapshot: () => { throw snapshotError; } },
|
||||
});
|
||||
await assert.rejects(
|
||||
snapshotRoute.handle({ method: 'GET', url: '/metrics' }, routeResponse()),
|
||||
(error) => error === snapshotError,
|
||||
);
|
||||
|
||||
const rendererRoute = createPrometheusMetricsRoute({
|
||||
deviceInventory: {
|
||||
metricsSnapshot: () => ({ traffic: { gatewayBytes: 'broken', proxyBytes: '0' } }),
|
||||
},
|
||||
});
|
||||
await assert.rejects(
|
||||
rendererRoute.handle({ method: 'GET', url: '/metrics' }, routeResponse()),
|
||||
/Invalid Prometheus counter/,
|
||||
);
|
||||
});
|
||||
|
||||
test('Prometheus route is the sole HTTP owner before API and static fallback', () => {
|
||||
const index = readFileSync(new URL('../../src/server/index.ts', import.meta.url), 'utf8');
|
||||
const route = readFileSync(
|
||||
new URL('../../src/server/http/routes/prometheusMetricsRoute.ts', import.meta.url),
|
||||
'utf8',
|
||||
);
|
||||
assert.match(index, /createPrometheusMetricsRoute\(\{ deviceInventory \}\)/);
|
||||
const delegation = index.indexOf('prometheusMetricsRoute.handle(req, res)');
|
||||
const apiDispatch = index.indexOf("requestUrl.pathname.startsWith('/api/')");
|
||||
const staticFallback = index.indexOf(': serveStatic(req, res)');
|
||||
assert.ok(delegation >= 0 && delegation < apiDispatch && apiDispatch < staticFallback);
|
||||
assert.doesNotMatch(index, /['"]\/metrics['"]/);
|
||||
assert.doesNotMatch(index, /metricsSnapshot\(\)|sendPrometheusMetrics/);
|
||||
assert.match(route, /pathname !== '\/metrics'/);
|
||||
assert.match(route, /deviceInventory\.metricsSnapshot\(\)/);
|
||||
assert.doesNotMatch(route, /\.refresh\(/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user