Merge pull request #19276 from stiyyagura0901/litellm_fix_ui_auth_header_override

fix: UI dashboard respects custom authentication header override
This commit is contained in:
yuneng-jiang
2026-01-20 12:24:14 -08:00
committed by GitHub
22 changed files with 64 additions and 60 deletions
@@ -1,4 +1,4 @@
import { getProxyBaseUrl } from "@/components/networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
import { useMutation } from "@tanstack/react-query";
interface CreateParams {
@@ -18,7 +18,7 @@ const performCloudZeroCreate = async (accessToken: string, params: CreateParams)
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
@@ -1,4 +1,4 @@
import { getProxyBaseUrl } from "@/components/networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
import { useMutation } from "@tanstack/react-query";
interface DryRunParams {
@@ -16,7 +16,7 @@ const performCloudZeroDryRun = async (accessToken: string, params: DryRunParams
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
@@ -1,4 +1,4 @@
import { getProxyBaseUrl } from "@/components/networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
import { useMutation } from "@tanstack/react-query";
interface ExportParams {
@@ -16,7 +16,7 @@ const performCloudZeroExport = async (accessToken: string, params: ExportParams
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
@@ -1,5 +1,5 @@
import { CloudZeroSettings } from "@/components/CloudZeroCostTracking/types";
import { getProxyBaseUrl } from "@/components/networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { createQueryKeys } from "../common/queryKeysFactory";
@@ -12,7 +12,7 @@ const getCloudZeroSettings = async (accessToken: string): Promise<CloudZeroSetti
const response = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
@@ -82,7 +82,7 @@ const updateCloudZeroSettings = async (accessToken: string, params: UpdateParams
const response = await fetch(url, {
method: "PUT",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
@@ -140,7 +140,7 @@ const deleteCloudZeroSettings = async (accessToken: string): Promise<DeleteRespo
const response = await fetch(url, {
method: "DELETE",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
@@ -7,6 +7,7 @@ import { RouterFieldsResponse, useRouterFields } from "./useRouterFields";
// Mock the networking module
vi.mock("@/components/networking", () => ({
proxyBaseUrl: null,
getGlobalLitellmHeaderName: vi.fn(() => "Authorization"),
}));
// Mock useAuthorized hook
@@ -1,7 +1,7 @@
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import { useQuery, UseQueryResult } from "@tanstack/react-query";
import { createQueryKeys } from "../common/queryKeysFactory";
import { proxyBaseUrl } from "@/components/networking";
import { proxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
export interface RouterSettingsField {
field_name: string;
@@ -39,7 +39,7 @@ const getRouterFields = async (accessToken: string): Promise<RouterFieldsRespons
const response = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
@@ -1,5 +1,5 @@
import { useState, useCallback, useRef, useEffect } from "react";
import { getProxyBaseUrl } from "@/components/networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
import NotificationsManager from "../../molecules/notifications_manager";
import { CostEstimateRequest, CostEstimateResponse } from "../types";
import { PricingFormValues } from "./types";
@@ -36,7 +36,7 @@ export function useCostEstimate(accessToken: string | null) {
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(requestBody),
@@ -1,5 +1,5 @@
import { useState, useCallback, useRef, useEffect } from "react";
import { getProxyBaseUrl } from "@/components/networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
import { CostEstimateRequest, CostEstimateResponse } from "../types";
import { ModelEntry, MultiModelResult } from "./types";
@@ -59,7 +59,7 @@ export function useMultiCostEstimate(accessToken: string | null) {
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(requestBody),
@@ -1,5 +1,5 @@
import { useState, useCallback } from "react";
import { getProxyBaseUrl } from "@/components/networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
import NotificationsManager from "../molecules/notifications_manager";
import { DiscountConfig } from "./types";
import { getProviderBackendValue } from "./provider_display_helpers";
@@ -32,7 +32,7 @@ export function useDiscountConfig({ accessToken }: UseDiscountConfigProps): UseD
const response = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
@@ -59,7 +59,7 @@ export function useDiscountConfig({ accessToken }: UseDiscountConfigProps): UseD
const response = await fetch(url, {
method: "PATCH",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(config),
@@ -1,5 +1,5 @@
import { useState, useCallback } from "react";
import { getProxyBaseUrl } from "@/components/networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
import NotificationsManager from "../molecules/notifications_manager";
import { MarginConfig } from "./types";
import { getProviderBackendValue } from "./provider_display_helpers";
@@ -42,7 +42,7 @@ export function useMarginConfig({ accessToken }: UseMarginConfigProps): UseMargi
const response = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
@@ -69,7 +69,7 @@ export function useMarginConfig({ accessToken }: UseMarginConfigProps): UseMargi
const response = await fetch(url, {
method: "PATCH",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(config),
@@ -1,6 +1,7 @@
import React, { useState, useEffect } from "react";
import { Text, Button, Callout, TextInput } from "@tremor/react";
import { Modal, Form, Spin, Select } from "antd";
import { getGlobalLitellmHeaderName } from "@/components/networking";
import NotificationsManager from "./molecules/notifications_manager";
interface CloudZeroExportModalProps {
@@ -43,7 +44,7 @@ const CloudZeroExportModal: React.FC<CloudZeroExportModalProps> = ({ isOpen, onC
const response = await fetch("/cloudzero/settings", {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
@@ -88,7 +89,7 @@ const CloudZeroExportModal: React.FC<CloudZeroExportModalProps> = ({ isOpen, onC
const response = await fetch(endpoint, {
method,
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
@@ -128,7 +129,7 @@ const CloudZeroExportModal: React.FC<CloudZeroExportModalProps> = ({ isOpen, onC
const response = await fetch("/cloudzero/export", {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
@@ -15,7 +15,7 @@ import {
Col,
Subtitle,
} from "@tremor/react";
import { getProxyBaseUrl } from "@/components/networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
import NotificationsManager from "./molecules/notifications_manager";
interface CostTrackingSettingsProps {
@@ -56,7 +56,7 @@ const CostTrackingSettings: React.FC<CostTrackingSettingsProps> = ({
const response = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
@@ -86,7 +86,7 @@ const CostTrackingSettings: React.FC<CostTrackingSettingsProps> = ({
const response = await fetch(url, {
method: "PATCH",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(discountConfig),
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
import { Form, Typography, Select, Input, Switch, Modal } from "antd";
import { Button, TextInput } from "@tremor/react";
import { guardrail_provider_map, guardrailLogoMap, getGuardrailProviders } from "./guardrail_info_helpers";
import { getGuardrailUISettings } from "../networking";
import { getGuardrailUISettings, getGlobalLitellmHeaderName } from "../networking";
import PiiConfiguration from "./pii_configuration";
import NotificationsManager from "../molecules/notifications_manager";
@@ -183,7 +183,7 @@ const EditGuardrailForm: React.FC<EditGuardrailFormProps> = ({
const response = await fetch(url, {
method: "PUT",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(guardrailData),
@@ -6256,7 +6256,7 @@ export const tagCreateCall = async (accessToken: string, formValues: TagNewReque
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
},
body: JSON.stringify(formValues),
});
@@ -6282,7 +6282,7 @@ export const tagUpdateCall = async (accessToken: string, formValues: TagUpdateRe
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
},
body: JSON.stringify(formValues),
});
@@ -6308,7 +6308,7 @@ export const tagInfoCall = async (accessToken: string, tagNames: string[]): Prom
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
},
body: JSON.stringify({ names: tagNames }),
});
@@ -6334,7 +6334,7 @@ export const tagListCall = async (accessToken: string): Promise<TagListResponse>
const response = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
},
});
@@ -6360,7 +6360,7 @@ export const tagDeleteCall = async (accessToken: string, tagName: string): Promi
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
},
body: JSON.stringify({ name: tagName }),
});
@@ -6452,7 +6452,7 @@ export const getTeamPermissionsCall = async (accessToken: string, teamId: string
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
},
});
@@ -6480,7 +6480,7 @@ export const teamPermissionsUpdateCall = async (accessToken: string, teamId: str
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
},
body: JSON.stringify({
team_id: teamId,
@@ -6544,7 +6544,7 @@ export const vectorStoreCreateCall = async (accessToken: string, formValues: Rec
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
},
body: JSON.stringify(formValues),
});
@@ -6573,7 +6573,7 @@ export const vectorStoreListCall = async (
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
},
});
@@ -6597,7 +6597,7 @@ export const vectorStoreDeleteCall = async (accessToken: string, vectorStoreId:
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
},
body: JSON.stringify({ vector_store_id: vectorStoreId }),
});
@@ -6622,7 +6622,7 @@ export const vectorStoreInfoCall = async (accessToken: string, vectorStoreId: st
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
},
body: JSON.stringify({ vector_store_id: vectorStoreId }),
});
@@ -6647,7 +6647,7 @@ export const vectorStoreUpdateCall = async (accessToken: string, formValues: Rec
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
},
body: JSON.stringify(formValues),
});
@@ -7768,7 +7768,7 @@ export const vectorStoreSearchCall = async (
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
@@ -7801,7 +7801,7 @@ export const searchToolQueryCall = async (
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
@@ -5,6 +5,7 @@ import CodeInterpreterOutput from "./CodeInterpreterOutput";
vi.mock("@/components/networking", () => ({
getProxyBaseUrl: vi.fn(() => "https://example.com"),
getGlobalLitellmHeaderName: vi.fn(() => "Authorization"),
}));
global.fetch = vi.fn();
@@ -9,7 +9,7 @@ import {
} from "@ant-design/icons";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { coy } from "react-syntax-highlighter/dist/esm/styles/prism";
import { getProxyBaseUrl } from "@/components/networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
interface ContainerFileCitation {
type: "container_file_citation";
@@ -55,7 +55,7 @@ const CodeInterpreterOutput: React.FC<CodeInterpreterOutputProps> = ({
`${proxyBaseUrl}/v1/containers/${annotation.container_id}/files/${annotation.file_id}/content`,
{
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
},
}
);
@@ -90,7 +90,7 @@ const CodeInterpreterOutput: React.FC<CodeInterpreterOutputProps> = ({
`${proxyBaseUrl}/v1/containers/${annotation.container_id}/files/${annotation.file_id}/content`,
{
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
},
}
);
@@ -2,7 +2,7 @@
// A2A Protocol (JSON-RPC 2.0) implementation for sending messages to agents
import { v4 as uuidv4 } from "uuid";
import { getProxyBaseUrl } from "../../networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "../../networking";
import { A2ATaskMetadata } from "../chat_ui/types";
interface A2AMessagePart {
@@ -143,7 +143,7 @@ export const makeA2ASendMessageRequest = async (
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(jsonRpcRequest),
@@ -276,7 +276,7 @@ export const makeA2AStreamMessageRequest = async (
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(jsonRpcRequest),
@@ -3,6 +3,7 @@ import { makeOpenAIEmbeddingsRequest } from "./embeddings_api";
vi.mock("@/components/networking", () => ({
getProxyBaseUrl: vi.fn(() => "https://example.com"),
getGlobalLitellmHeaderName: vi.fn(() => "Authorization"),
}));
describe("embeddings_api", () => {
@@ -1,5 +1,5 @@
import NotificationManager from "@/components/molecules/notifications_manager";
import { getProxyBaseUrl } from "@/components/networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
export async function makeOpenAIEmbeddingsRequest(
input: string,
@@ -34,7 +34,7 @@ export async function makeOpenAIEmbeddingsRequest(
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
...headers,
},
body: JSON.stringify({
@@ -1,6 +1,6 @@
// fetch_agents.tsx
import { getProxyBaseUrl } from "../../networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "../../networking";
export interface Agent {
agent_id: string;
@@ -27,7 +27,7 @@ export const fetchAvailableAgents = async (
const response = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
@@ -3,7 +3,7 @@ import NotificationsManager from "../../../molecules/notifications_manager";
import { TokenUsage } from "../../../playground/chat_ui/ResponseMetrics";
import { Message } from "./types";
import { convertToDotPrompt, extractVariables } from "../utils";
import { getProxyBaseUrl } from "../../../networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "../../../networking";
export const useConversation = (prompt: any, accessToken: string | null) => {
const [isLoading, setIsLoading] = useState(false);
@@ -91,7 +91,7 @@ export const useConversation = (prompt: any, accessToken: string | null) => {
const response = await fetch(`${proxyBaseUrl}/prompts/test`, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(requestBody),
@@ -1,7 +1,7 @@
import React, { useState, useEffect } from "react";
import { Card, Title, Text, TextInput, Button } from "@tremor/react";
import { useTheme } from "@/contexts/ThemeContext";
import { getProxyBaseUrl } from "@/components/networking";
import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking";
import NotificationsManager from "./molecules/notifications_manager";
interface UIThemeSettingsProps {
@@ -29,7 +29,7 @@ const UIThemeSettings: React.FC<UIThemeSettingsProps> = ({ userID, userRole, acc
const response = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
@@ -53,7 +53,7 @@ const UIThemeSettings: React.FC<UIThemeSettingsProps> = ({ userID, userRole, acc
const response = await fetch(url, {
method: "PATCH",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
@@ -87,7 +87,7 @@ const UIThemeSettings: React.FC<UIThemeSettingsProps> = ({ userID, userRole, acc
const response = await fetch(url, {
method: "PATCH",
headers: {
Authorization: `Bearer ${accessToken}`,
[getGlobalLitellmHeaderName()]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({