fix(e2e): bound image auth mock bodies

This commit is contained in:
Vincent Koc
2026-06-03 13:15:46 +02:00
parent 529282dcff
commit 87eaac4010
3 changed files with 53 additions and 17 deletions

View File

@@ -63,6 +63,7 @@ Docs: https://docs.openclaw.ai
- Release/CI/E2E: stop tracked gateway and mock service process groups so descendant helpers do not survive E2E cleanup.
- Release/CI/E2E: exit Telegram credential proof wrappers promptly after forwarded shutdown signals while keeping the descendant force-kill guard armed.
- Release/CI/E2E: reject oversized ClickClack fixture request bodies before release journey smokes can accumulate unbounded payloads.
- Release/CI/E2E: reject oversized OpenAI image-auth mock request bodies before Docker proof runs can accumulate unbounded payloads.
- Release/CI/E2E: fail secret-provider proof runs when temporary state cleanup still fails after retries instead of hiding the cleanup error.
- Release/CI/E2E: fail package-candidate ref proofs when temporary source worktree cleanup fails instead of leaving stale worktrees behind.
- Release/CI/E2E: remove package tarball extract directories when tar extraction fails before validation can continue.

View File

@@ -1,12 +1,15 @@
import http from "node:http";
import type { AddressInfo } from "node:net";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { isRequestBodyTooLargeError, readBody } from "./lib/mock-openai-http.mjs";
const DIRECT_IMAGE_BYTES = Buffer.from("docker-direct-image");
const CODEX_IMAGE_BYTES = Buffer.from("docker-codex-image");
const DIRECT_TOKEN = "sk-openclaw-image-auth-e2e";
const CODEX_TOKEN = "docker-codex-oauth-token";
type RequestRecord = {
export type RequestRecord = {
method?: string;
url?: string;
authorization?: string;
@@ -21,18 +24,6 @@ function assert(condition: unknown, message: string): asserts condition {
}
}
function readBody(req: http.IncomingMessage): Promise<string> {
return new Promise((resolve, reject) => {
let body = "";
req.setEncoding("utf8");
req.on("data", (chunk) => {
body += chunk;
});
req.on("end", () => resolve(body));
req.on("error", reject);
});
}
function writeJson(res: http.ServerResponse, status: number, body: unknown): void {
res.writeHead(status, { "content-type": "application/json" });
res.end(JSON.stringify(body));
@@ -63,14 +54,23 @@ function writeCodexSse(res: http.ServerResponse): void {
res.end("data: [DONE]\n\n");
}
async function startMockServer(records: RequestRecord[]): Promise<{
export async function startMockServer(records: RequestRecord[]): Promise<{
baseUrl: string;
close: () => Promise<void>;
}> {
const server = http.createServer((req, res) => {
void (async () => {
try {
const body = await readBody(req);
let body: string;
try {
body = await readBody(req);
} catch (error) {
if (isRequestBodyTooLargeError(error)) {
writeJson(res, 413, { error: { message: error.message } });
return;
}
throw error;
}
records.push({
method: req.method,
url: req.url,
@@ -164,7 +164,7 @@ function createCodexOAuthStore() {
} as const;
}
async function main() {
export async function main() {
assert(
process.env.OPENAI_API_KEY === DIRECT_TOKEN,
"Docker lane must expose the direct OpenAI API key",
@@ -246,4 +246,6 @@ async function main() {
}
}
await main();
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
await main();
}

View File

@@ -0,0 +1,33 @@
import { describe, expect, it } from "vitest";
import {
startMockServer,
type RequestRecord,
} from "../../scripts/e2e/openai-image-auth-docker-client.ts";
describe("OpenAI image auth Docker client mock server", () => {
it("rejects oversized request bodies before recording them", async () => {
const previousLimit = process.env.OPENCLAW_MOCK_OPENAI_REQUEST_MAX_BYTES;
process.env.OPENCLAW_MOCK_OPENAI_REQUEST_MAX_BYTES = "4";
const records: RequestRecord[] = [];
const server = await startMockServer(records);
try {
const response = await fetch(`${server.baseUrl}/v1/images/generations`, {
method: "POST",
body: "too large",
});
await expect(response.json()).resolves.toEqual({
error: { message: "mock OpenAI request body exceeded 4 bytes" },
});
expect(response.status).toBe(413);
expect(records).toEqual([]);
} finally {
await server.close();
if (previousLimit === undefined) {
delete process.env.OPENCLAW_MOCK_OPENAI_REQUEST_MAX_BYTES;
} else {
process.env.OPENCLAW_MOCK_OPENAI_REQUEST_MAX_BYTES = previousLimit;
}
}
});
});