Files
openclaw/extensions/msteams/src/monitor.test.ts
2026-03-02 20:34:05 +00:00

86 lines
2.7 KiB
TypeScript

import { once } from "node:events";
import type { Server } from "node:http";
import { createConnection, type AddressInfo } from "node:net";
import express from "express";
import { describe, expect, it } from "vitest";
import { applyMSTeamsWebhookTimeouts } from "./monitor.js";
async function closeServer(server: Server): Promise<void> {
await new Promise<void>((resolve) => {
server.close(() => resolve());
});
}
async function waitForSlowBodySocketClose(port: number, timeoutMs: number): Promise<number> {
return new Promise<number>((resolve, reject) => {
const startedAt = Date.now();
const socket = createConnection({ host: "127.0.0.1", port }, () => {
socket.write("POST /api/messages HTTP/1.1\r\n");
socket.write("Host: localhost\r\n");
socket.write("Content-Type: application/json\r\n");
socket.write("Content-Length: 1048576\r\n");
socket.write("\r\n");
socket.write('{"type":"message"');
});
socket.on("error", () => {
// ECONNRESET is expected once the server drops the socket.
});
const failTimer = setTimeout(() => {
socket.destroy();
reject(new Error(`socket stayed open for ${timeoutMs}ms`));
}, timeoutMs);
socket.on("close", () => {
clearTimeout(failTimer);
resolve(Date.now() - startedAt);
});
});
}
describe("msteams monitor webhook hardening", () => {
it("applies explicit webhook timeout values", async () => {
const app = express();
const server = app.listen(0, "127.0.0.1");
await once(server, "listening");
try {
applyMSTeamsWebhookTimeouts(server, {
inactivityTimeoutMs: 3210,
requestTimeoutMs: 6543,
headersTimeoutMs: 9876,
});
expect(server.timeout).toBe(3210);
expect(server.requestTimeout).toBe(6543);
expect(server.headersTimeout).toBe(6543);
} finally {
await closeServer(server);
}
});
it("drops slow-body webhook requests within configured inactivity timeout", async () => {
const app = express();
app.use(express.json({ limit: "1mb" }));
app.use((_req, res, _next) => {
res.status(401).end("unauthorized");
});
app.post("/api/messages", (_req, res) => {
res.end("ok");
});
const server = app.listen(0, "127.0.0.1");
await once(server, "listening");
try {
applyMSTeamsWebhookTimeouts(server, {
inactivityTimeoutMs: 400,
requestTimeoutMs: 1500,
headersTimeoutMs: 1500,
});
const port = (server.address() as AddressInfo).port;
const closedMs = await waitForSlowBodySocketClose(port, 3000);
expect(closedMs).toBeLessThan(2500);
} finally {
await closeServer(server);
}
});
});