项目文件夹

文件
2026-07-13 13:39:12 +08:00

72 行
2.8 KiB
TypeScript

/**
* Regression for #5899 (PR #5920): the OpenAI-compatible models-discovery URL
* builder must strip a trailing `/v1` UNCONDITIONALLY before appending
* `/v1/models`. A gateway baseUrl like ".../v1/chat/completions" was reduced to
* ".../v1" (the old `else if` skipped the /v1 strip once `/chat/completions`
* matched) and then produced ".../v1/v1/models" — a 308 redirect that blocked
* model discovery. The fix converts the `/v1` strip to an independent `if`
* (guarding against a literal "scheme://v1" authority) in BOTH the general
* discovery path and the `provider === "openai"` custom-base-URL path.
*/
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-5899-"));
process.env.DATA_DIR = TEST_DATA_DIR;
const core = await import("../../src/lib/db/core.ts");
const providersDb = await import("../../src/lib/db/providers.ts");
const modelsRoute = await import("../../src/app/api/providers/[id]/models/route.ts");
test.after(() => {
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
});
test("#5899 openai gateway baseUrl ending in /v1/chat/completions never probes /v1/v1/models", async () => {
const connection = await providersDb.createProviderConnection({
provider: "openai",
authType: "apikey",
name: "airforce-gateway",
apiKey: "sk-airforce",
providerSpecificData: { baseUrl: "https://api.airforce/v1/chat/completions" },
});
const requestedUrls: string[] = [];
const originalFetch = globalThis.fetch;
globalThis.fetch = async (url) => {
const u = String(url);
requestedUrls.push(u);
// The correctly-stripped candidate must be the one that serves models.
if (u === "https://api.airforce/v1/models") {
return Response.json({ object: "list", data: [{ id: "gpt-4o" }, { id: "gpt-5" }] });
}
// The double-prefixed URL upstream answered with a 308 redirect (#5899).
if (u === "https://api.airforce/v1/v1/models") {
return new Response(null, { status: 308, headers: { location: u } });
}
return new Response("not found", { status: 404 });
};
try {
await modelsRoute.GET(
new Request(`http://localhost/api/providers/${connection.id}/models?refresh=true`),
{ params: { id: connection.id } }
);
} finally {
globalThis.fetch = originalFetch;
}
assert.ok(
requestedUrls.includes("https://api.airforce/v1/models"),
`expected a request to the correctly-stripped /v1/models URL; got: ${JSON.stringify(requestedUrls)}`
);
assert.ok(
!requestedUrls.includes("https://api.airforce/v1/v1/models"),
`must never probe the double-prefixed /v1/v1/models URL; got: ${JSON.stringify(requestedUrls)}`
);
});