|
1 | 1 | import http from "node:http"; |
2 | 2 | import type { AddressInfo } from "node:net"; |
| 3 | +import path from "node:path"; |
| 4 | +import { fileURLToPath } from "node:url"; |
| 5 | +import { isRequestBodyTooLargeError, readBody } from "./lib/mock-openai-http.mjs"; |
3 | 6 | |
4 | 7 | const DIRECT_IMAGE_BYTES = Buffer.from("docker-direct-image"); |
5 | 8 | const CODEX_IMAGE_BYTES = Buffer.from("docker-codex-image"); |
6 | 9 | const DIRECT_TOKEN = "sk-openclaw-image-auth-e2e"; |
7 | 10 | const CODEX_TOKEN = "docker-codex-oauth-token"; |
8 | 11 | |
9 | | -type RequestRecord = { |
| 12 | +export type RequestRecord = { |
10 | 13 | method?: string; |
11 | 14 | url?: string; |
12 | 15 | authorization?: string; |
@@ -21,18 +24,6 @@ function assert(condition: unknown, message: string): asserts condition {
|
21 | 24 | } |
22 | 25 | } |
23 | 26 | |
24 | | -function readBody(req: http.IncomingMessage): Promise<string> { |
25 | | -return new Promise((resolve, reject) => { |
26 | | -let body = ""; |
27 | | -req.setEncoding("utf8"); |
28 | | -req.on("data", (chunk) => { |
29 | | -body += chunk; |
30 | | -}); |
31 | | -req.on("end", () => resolve(body)); |
32 | | -req.on("error", reject); |
33 | | -}); |
34 | | -} |
35 | | - |
36 | 27 | function writeJson(res: http.ServerResponse, status: number, body: unknown): void { |
37 | 28 | res.writeHead(status, { "content-type": "application/json" }); |
38 | 29 | res.end(JSON.stringify(body)); |
@@ -63,14 +54,23 @@ function writeCodexSse(res: http.ServerResponse): void {
|
63 | 54 | res.end("data: [DONE]\n\n"); |
64 | 55 | } |
65 | 56 | |
66 | | -async function startMockServer(records: RequestRecord[]): Promise<{ |
| 57 | +export async function startMockServer(records: RequestRecord[]): Promise<{ |
67 | 58 | baseUrl: string; |
68 | 59 | close: () => Promise<void>; |
69 | 60 | }> { |
70 | 61 | const server = http.createServer((req, res) => { |
71 | 62 | void (async () => { |
72 | 63 | try { |
73 | | -const body = await readBody(req); |
| 64 | +let body: string; |
| 65 | +try { |
| 66 | +body = await readBody(req); |
| 67 | +} catch (error) { |
| 68 | +if (isRequestBodyTooLargeError(error)) { |
| 69 | +writeJson(res, 413, { error: { message: error.message } }); |
| 70 | +return; |
| 71 | +} |
| 72 | +throw error; |
| 73 | +} |
74 | 74 | records.push({ |
75 | 75 | method: req.method, |
76 | 76 | url: req.url, |
@@ -164,7 +164,7 @@ function createCodexOAuthStore() {
|
164 | 164 | } as const; |
165 | 165 | } |
166 | 166 | |
167 | | -async function main() { |
| 167 | +export async function main() { |
168 | 168 | assert( |
169 | 169 | process.env.OPENAI_API_KEY === DIRECT_TOKEN, |
170 | 170 | "Docker lane must expose the direct OpenAI API key", |
@@ -246,4 +246,6 @@ async function main() {
|
246 | 246 | } |
247 | 247 | } |
248 | 248 | |
249 | | -await main(); |
| 249 | +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { |
| 250 | +await main(); |
| 251 | +} |