Add native traffic inspection to Harbor Connect and Gateway
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import type { IncomingMessage, ServerResponse } from 'node:http';
|
||||
|
||||
import {
|
||||
assertLiveTrafficSnapshot,
|
||||
type LiveTrafficSnapshot,
|
||||
} from '../../../shared/liveTraffic.js';
|
||||
import { HarborError } from '../../../shared/errors.js';
|
||||
import { sendJson } from '../response.js';
|
||||
|
||||
interface LiveTrafficReader {
|
||||
snapshot(): unknown | Promise<unknown>;
|
||||
}
|
||||
|
||||
interface DeviceInventoryReader {
|
||||
snapshot(): unknown;
|
||||
}
|
||||
|
||||
function record(value: unknown): Record<string, unknown> {
|
||||
return value && typeof value === 'object' && !Array.isArray(value)
|
||||
? value as Record<string, unknown>
|
||||
: {};
|
||||
}
|
||||
|
||||
export function enrichLiveTrafficDeviceLabels(
|
||||
snapshot: LiveTrafficSnapshot,
|
||||
inventory: unknown,
|
||||
): LiveTrafficSnapshot {
|
||||
const devices = Array.isArray(record(inventory).devices)
|
||||
? (record(inventory).devices as unknown[]).map(record)
|
||||
: [];
|
||||
const labels = new Map(devices.flatMap((device) => {
|
||||
const id = String(device.id || '');
|
||||
if (!/^dev_[a-f0-9]{16}$/.test(id)) return [];
|
||||
const label = [device.alias, device.hostname, device.ip]
|
||||
.find((value) => typeof value === 'string' && value.trim());
|
||||
return label ? [[id, String(label).trim()] as const] : [];
|
||||
}));
|
||||
if (!labels.size) return snapshot;
|
||||
return {
|
||||
...snapshot,
|
||||
connections: snapshot.connections.map((connection) => {
|
||||
const label = connection.origin.kind === 'device' && connection.origin.id
|
||||
? labels.get(connection.origin.id)
|
||||
: null;
|
||||
return label ? {
|
||||
...connection,
|
||||
origin: { ...connection.origin, label },
|
||||
} : connection;
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
export function createLiveTrafficRoute({
|
||||
traffic,
|
||||
deviceInventory = null,
|
||||
}: {
|
||||
traffic: LiveTrafficReader | null;
|
||||
deviceInventory?: DeviceInventoryReader | null;
|
||||
}) {
|
||||
return {
|
||||
async handle(req: IncomingMessage, res: ServerResponse) {
|
||||
const pathname = new URL(req.url || '/', 'http://localhost').pathname;
|
||||
if (pathname !== '/api/traffic/live') return false;
|
||||
if (req.method !== 'GET' || !traffic) throw new HarborError('ENDPOINT_NOT_FOUND');
|
||||
const snapshot = assertLiveTrafficSnapshot(await traffic.snapshot());
|
||||
const enriched = deviceInventory
|
||||
? enrichLiveTrafficDeviceLabels(snapshot, deviceInventory.snapshot())
|
||||
: snapshot;
|
||||
sendJson(res, 200, enriched);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user