fix: normalize wildcard gateway URLs for Codex

This commit is contained in:
2026-07-20 10:01:19 +08:00
parent 31e673f777
commit 14fae29618
6 changed files with 237 additions and 38 deletions
+59 -5
View File
@@ -638,14 +638,18 @@ async function run() {
const gatewayPort = await getFreePort();
const configPath = path.join(tempRoot, "config.json");
const logPath = path.join(tempRoot, "gateway.log");
const codexConfigPath = path.join(tempRoot, ".codex", "config.toml");
const profilesDir = path.join(tempRoot, ".config", "codex-retry-gateway", "profiles");
const imageProfilesDir = path.join(tempRoot, ".config", "codex-retry-gateway", "image-profiles");
const gatewayBaseUrl = `http://127.0.0.1:${gatewayPort}`;
const legacyWildcardGatewayBaseUrl = `http://0.0.0.0:${gatewayPort}`;
const upstreamBaseUrl = `http://127.0.0.1:${upstreamPort}`;
const config = {
profile_name: "legacy-text",
listen_host: "127.0.0.1",
listen_host: "0.0.0.0",
listen_port: gatewayPort,
upstream_base_url: `http://127.0.0.1:${upstreamPort}`,
upstream_base_url: upstreamBaseUrl,
image_base_url: `http://127.0.0.1:${imageUpstreamPort}`,
image_auth_mode: "fixed_bearer",
image_auth_env: "TEST_CODEX_RETRY_GATEWAY_IMAGE_API_KEY",
@@ -672,12 +676,39 @@ async function run() {
await writeFile(
path.join(profilesDir, "legacy-text.env"),
[
`CODEX_RETRY_GATEWAY_UPSTREAM_BASE_URL=http://127.0.0.1:${upstreamPort}`,
"CODEX_RETRY_GATEWAY_LISTEN_HOST=0.0.0.0",
`CODEX_RETRY_GATEWAY_LISTEN_PORT=${gatewayPort}`,
`CODEX_RETRY_GATEWAY_UPSTREAM_BASE_URL=${upstreamBaseUrl}`,
"CODEX_RETRY_GATEWAY_UPSTREAM_AUTH_MODE=passthrough",
"",
].join("\n"),
"utf8",
);
await mkdir(path.dirname(codexConfigPath), { recursive: true });
await writeFile(
codexConfigPath,
[
'model_provider = "custom"',
"",
"[model_providers.custom]",
'name = "Gateway E2E Test"',
`base_url = "${legacyWildcardGatewayBaseUrl}"`,
'wire_api = "responses"',
"",
].join("\n"),
"utf8",
);
await writeFile(
path.join(tempRoot, "state.json"),
`${JSON.stringify({
codex_config_path: codexConfigPath,
provider_name: "custom",
original_base_url: upstreamBaseUrl,
gateway_base_url: legacyWildcardGatewayBaseUrl,
profile_name: "legacy-text",
}, null, 2)}\n`,
"utf8",
);
await writeFile(configPath, JSON.stringify(config, null, 2), "utf8");
const upstream = await startFakeUpstream(upstreamPort, { label: "default" });
@@ -1036,7 +1067,7 @@ async function run() {
headers: { ...adminHeaders, "content-type": "application/json" },
body: JSON.stringify({
name: "legacy-text",
listen_host: "127.0.0.1",
listen_host: "0.0.0.0",
listen_port: gatewayPort,
upstream_base_url: `http://127.0.0.1:${upstreamPort}`,
auth_mode: "passthrough",
@@ -1044,6 +1075,29 @@ async function run() {
},
);
assert(saveActiveTextProfileResponse.status === 200, `当前文本 profile 保存失败: ${saveActiveTextProfileResponse.status}`);
const saveActiveTextProfilePayload = await saveActiveTextProfileResponse.json();
assert(
saveActiveTextProfilePayload?.applied_profile?.codex_provider_sync?.updated === true,
"保存活跃 wildcard listener profile 时未同步 Codex provider",
);
assert(
saveActiveTextProfilePayload?.applied_profile?.codex_provider_sync?.gateway_base_url === gatewayBaseUrl,
"保存活跃 wildcard listener profile 时未使用回环 gateway URL",
);
const savedCodexConfig = await readFile(codexConfigPath, "utf8");
assert(
savedCodexConfig.includes(`base_url = "${gatewayBaseUrl}"`),
"保存 wildcard listener profile 后 Codex config 未指向 127.0.0.1",
);
assert(
!savedCodexConfig.includes(`base_url = "${legacyWildcardGatewayBaseUrl}"`),
"保存 wildcard listener profile 后 Codex config 仍指向 0.0.0.0",
);
const savedState = JSON.parse(await readFile(path.join(tempRoot, "state.json"), "utf8"));
assert(savedState.gateway_base_url === gatewayBaseUrl, "runtime state 未规范化 wildcard gateway URL");
assert(savedState.original_base_url === upstreamBaseUrl, "同步 Codex config 时覆盖了原始上游 URL");
assert(savedState.latest_backup_path, "同步 Codex config 时未创建可恢复备份");
assert((await stat(savedState.latest_backup_path)).isFile(), "Codex config 备份文件不存在");
const afterTextSaveStatusResponse = await fetch(`http://127.0.0.1:${gatewayPort}/__codex_retry_gateway/api/status`, { headers: adminHeaders });
const afterTextSaveStatusPayload = await afterTextSaveStatusResponse.json();
assert(afterTextSaveStatusPayload?.config?.image_profile_name === "image-primary", "保存文本 profile 不应重置图片 profile");