From 163c1ac29dab6a58dd3aa870dddbb2412ab0ca5c Mon Sep 17 00:00:00 2001 From: Supra4E8C Date: Fri, 27 Mar 2026 22:03:57 +0800 Subject: [PATCH] fix(openai): treat Authorization header as case-insensitive --- src/pages/AiProvidersOpenAIEditPage.tsx | 4 ++-- src/pages/AiProvidersOpenAIModelsPage.tsx | 4 ++-- src/services/api/models.ts | 8 +++----- src/utils/headers.ts | 6 ++++++ 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/pages/AiProvidersOpenAIEditPage.tsx b/src/pages/AiProvidersOpenAIEditPage.tsx index 4bf90395..25e23088 100644 --- a/src/pages/AiProvidersOpenAIEditPage.tsx +++ b/src/pages/AiProvidersOpenAIEditPage.tsx @@ -12,7 +12,7 @@ import { useEdgeSwipeBack } from '@/hooks/useEdgeSwipeBack'; import { useNotificationStore } from '@/stores'; import { apiCallApi, getApiCallErrorMessage } from '@/services/api'; import type { ApiKeyEntry } from '@/types'; -import { buildHeaderObject } from '@/utils/headers'; +import { buildHeaderObject, hasHeader } from '@/utils/headers'; import { buildApiKeyEntry, buildOpenAIChatCompletionsEndpoint } from '@/components/providers/utils'; import type { OpenAIEditOutletContext } from './AiProvidersOpenAIEditLayout'; import type { KeyTestStatus } from '@/stores/useOpenAIEditDraftStore'; @@ -213,7 +213,7 @@ export function AiProvidersOpenAIEditPage() { 'Content-Type': 'application/json', ...customHeaders, }; - if (!headers.Authorization && !headers['authorization']) { + if (!hasHeader(headers, 'authorization')) { headers.Authorization = `Bearer ${keyEntry.apiKey.trim()}`; } diff --git a/src/pages/AiProvidersOpenAIModelsPage.tsx b/src/pages/AiProvidersOpenAIModelsPage.tsx index e7765c92..ac5ec7d7 100644 --- a/src/pages/AiProvidersOpenAIModelsPage.tsx +++ b/src/pages/AiProvidersOpenAIModelsPage.tsx @@ -9,7 +9,7 @@ import { SecondaryScreenShell } from '@/components/common/SecondaryScreenShell'; import { useEdgeSwipeBack } from '@/hooks/useEdgeSwipeBack'; import { modelsApi } from '@/services/api'; import type { ModelInfo } from '@/utils/models'; -import { buildHeaderObject } from '@/utils/headers'; +import { buildHeaderObject, hasHeader } from '@/utils/headers'; import { buildOpenAIModelsEndpoint } from '@/components/providers/utils'; import type { OpenAIEditOutletContext } from './AiProvidersOpenAIEditLayout'; import styles from './AiProvidersPage.module.scss'; @@ -68,7 +68,7 @@ export function AiProvidersOpenAIModelsPage() { try { const headerObject = buildHeaderObject(form.headers); const firstKey = form.apiKeyEntries.find((entry) => entry.apiKey?.trim())?.apiKey?.trim(); - const hasAuthHeader = Boolean(headerObject.Authorization || headerObject['authorization']); + const hasAuthHeader = hasHeader(headerObject, 'authorization'); const list = await modelsApi.fetchModelsViaApiCall( trimmedBaseUrl, hasAuthHeader ? undefined : firstKey, diff --git a/src/services/api/models.ts b/src/services/api/models.ts index 158146b0..b18886da 100644 --- a/src/services/api/models.ts +++ b/src/services/api/models.ts @@ -90,7 +90,7 @@ export const modelsApi = { } const resolvedHeaders = { ...headers }; - if (apiKey) { + if (apiKey && !hasHeader(resolvedHeaders, 'authorization')) { resolvedHeaders.Authorization = `Bearer ${apiKey}`; } @@ -116,8 +116,7 @@ export const modelsApi = { } const resolvedHeaders = { ...headers }; - const hasAuthHeader = Boolean(resolvedHeaders.Authorization || resolvedHeaders.authorization); - if (apiKey && !hasAuthHeader) { + if (apiKey && !hasHeader(resolvedHeaders, 'authorization')) { resolvedHeaders.Authorization = `Bearer ${apiKey}`; } @@ -149,8 +148,7 @@ export const modelsApi = { } const resolvedHeaders = { ...headers }; - const hasAuthHeader = Boolean(resolvedHeaders.Authorization || resolvedHeaders.authorization); - if (apiKey && !hasAuthHeader) { + if (apiKey && !hasHeader(resolvedHeaders, 'authorization')) { resolvedHeaders.Authorization = `Bearer ${apiKey}`; } diff --git a/src/utils/headers.ts b/src/utils/headers.ts index 255371a3..a871cd23 100644 --- a/src/utils/headers.ts +++ b/src/utils/headers.ts @@ -31,6 +31,12 @@ export function buildHeaderObject(input?: HeaderEntry[] | Record | null | undefined, name: string): boolean { + if (!headers) return false; + const target = name.toLowerCase(); + return Object.keys(headers).some((key) => key.toLowerCase() === target); +} + export function headersToEntries(headers?: Record): HeaderEntry[] { if (!headers || typeof headers !== 'object') return []; return Object.entries(headers)