mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-13 18:52:18 +03:00
fix(deepseek-web): classify business auth rejection as 401 (#10218)
This commit is contained in:
@@ -116,6 +116,7 @@ export async function validateDeepSeekWebProvider({ apiKey }: any) {
|
||||
return {
|
||||
valid: false,
|
||||
error: "userToken is invalid or expired — get a fresh one from localStorage",
|
||||
statusCode: resp.status,
|
||||
};
|
||||
}
|
||||
if (!resp.ok) {
|
||||
@@ -123,6 +124,20 @@ export async function validateDeepSeekWebProvider({ apiKey }: any) {
|
||||
}
|
||||
const json = await resp.json();
|
||||
const bizData = json?.data?.biz_data || json?.biz_data;
|
||||
|
||||
// DeepSeek's web endpoint can report auth rejection as HTTP 200 with an
|
||||
// application-level error envelope. Code 40003 is the observed
|
||||
// "Authorization Failed" signal. Preserve the real HTTP behavior while
|
||||
// returning an auth-classifiable status to OmniRoute's connection-test
|
||||
// layer so it is not collapsed into a generic upstream_error.
|
||||
if (Number(json?.code) === 40003) {
|
||||
return {
|
||||
valid: false,
|
||||
error: "userToken is invalid or expired — get a fresh one from localStorage",
|
||||
statusCode: 401,
|
||||
};
|
||||
}
|
||||
|
||||
if (!bizData?.token) {
|
||||
return {
|
||||
valid: false,
|
||||
|
||||
132
tests/unit/deepseek-web-auth-semantics.test.ts
Normal file
132
tests/unit/deepseek-web-auth-semantics.test.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
const { validateDeepSeekWebProvider } = await import(
|
||||
"../../src/lib/providers/validation/webProvidersA.ts"
|
||||
);
|
||||
const { classifyFailure } = await import(
|
||||
"../../src/app/api/providers/[id]/test/route.ts"
|
||||
);
|
||||
|
||||
const SYNTHETIC_INVALID_TOKEN = "omniroute-auth-keeper-invalid-session-deepseek";
|
||||
|
||||
type DeepSeekValidationResult = Awaited<ReturnType<typeof validateDeepSeekWebProvider>>;
|
||||
|
||||
function statusCodeOf(result: DeepSeekValidationResult): number | undefined {
|
||||
if ("statusCode" in result && typeof result.statusCode === "number") {
|
||||
return result.statusCode;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async function withFetchResponse(body: unknown, status: number, fn: () => Promise<void>) {
|
||||
const originalFetch = globalThis.fetch;
|
||||
globalThis.fetch = async () =>
|
||||
new Response(JSON.stringify(body), {
|
||||
status,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
|
||||
try {
|
||||
await fn();
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch;
|
||||
}
|
||||
}
|
||||
|
||||
test("DeepSeek HTTP 200 code 40003 is surfaced as auth-classifiable 401", async () => {
|
||||
await withFetchResponse(
|
||||
{
|
||||
code: 40003,
|
||||
msg: "Authorization Failed",
|
||||
data: { biz_data: null },
|
||||
},
|
||||
200,
|
||||
async () => {
|
||||
const result = await validateDeepSeekWebProvider({
|
||||
apiKey: SYNTHETIC_INVALID_TOKEN,
|
||||
});
|
||||
const statusCode = statusCodeOf(result);
|
||||
|
||||
assert.equal(result.valid, false);
|
||||
assert.equal(statusCode, 401);
|
||||
assert.match(String(result.error ?? ""), /invalid or expired/i);
|
||||
assert.doesNotMatch(String(result.error ?? ""), new RegExp(SYNTHETIC_INVALID_TOKEN));
|
||||
|
||||
const diagnosis = classifyFailure({
|
||||
error: result.error,
|
||||
statusCode,
|
||||
provider: "deepseek-web",
|
||||
});
|
||||
assert.equal(diagnosis.type, "upstream_auth_error");
|
||||
assert.equal(diagnosis.code, "401");
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("DeepSeek unknown HTTP 200 business failure is not synthesized into 401", async () => {
|
||||
await withFetchResponse(
|
||||
{
|
||||
code: 49999,
|
||||
msg: "Temporary provider condition",
|
||||
data: { biz_data: null },
|
||||
},
|
||||
200,
|
||||
async () => {
|
||||
const result = await validateDeepSeekWebProvider({
|
||||
apiKey: SYNTHETIC_INVALID_TOKEN,
|
||||
});
|
||||
const statusCode = statusCodeOf(result);
|
||||
|
||||
assert.equal(result.valid, false);
|
||||
assert.equal(statusCode, undefined);
|
||||
|
||||
const diagnosis = classifyFailure({
|
||||
error: result.error,
|
||||
statusCode,
|
||||
provider: "deepseek-web",
|
||||
});
|
||||
assert.equal(diagnosis.type, "upstream_error");
|
||||
assert.equal(diagnosis.code, "upstream_error");
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("DeepSeek literal 401 and 403 preserve their HTTP auth status", async () => {
|
||||
for (const status of [401, 403]) {
|
||||
await withFetchResponse({}, status, async () => {
|
||||
const result = await validateDeepSeekWebProvider({
|
||||
apiKey: SYNTHETIC_INVALID_TOKEN,
|
||||
});
|
||||
const statusCode = statusCodeOf(result);
|
||||
|
||||
assert.equal(result.valid, false);
|
||||
assert.equal(statusCode, status);
|
||||
|
||||
const diagnosis = classifyFailure({
|
||||
error: result.error,
|
||||
statusCode,
|
||||
provider: "deepseek-web",
|
||||
});
|
||||
assert.equal(diagnosis.type, "upstream_auth_error");
|
||||
assert.equal(diagnosis.code, String(status));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test("DeepSeek valid HTTP 200 response with derived token remains healthy", async () => {
|
||||
await withFetchResponse(
|
||||
{
|
||||
code: 0,
|
||||
msg: "",
|
||||
data: { biz_data: { token: "synthetic-derived-access-token" } },
|
||||
},
|
||||
200,
|
||||
async () => {
|
||||
const result = await validateDeepSeekWebProvider({
|
||||
apiKey: "synthetic-valid-user-token",
|
||||
});
|
||||
assert.deepEqual(result, { valid: true, error: null });
|
||||
}
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user