mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
Change /public fields to honor server root path (#16930)
This commit is contained in:
parent
6ae22908b7
commit
5dd2ee0bff
2 changed files with 188 additions and 5 deletions
|
|
@ -132,3 +132,188 @@ describe("daily activity helpers", () => {
|
|||
expect(urlWithTeams.searchParams.get("exclude_team_ids")).toBe("litellm-dashboard");
|
||||
});
|
||||
});
|
||||
|
||||
describe("UI config and public endpoints", () => {
|
||||
const originalFetch = global.fetch;
|
||||
|
||||
const setupMockFetch = (responses: Array<{ url: string; data: any }>) => {
|
||||
const mockFetch = vi.fn().mockImplementation((url: string) => {
|
||||
const response = responses.find((r) => url.includes(r.url));
|
||||
if (response) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
json: vi.fn().mockResolvedValue(response.data),
|
||||
} as any);
|
||||
}
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
json: vi.fn().mockResolvedValue({}),
|
||||
} as any);
|
||||
});
|
||||
global.fetch = mockFetch as any;
|
||||
return mockFetch;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
global.fetch = originalFetch;
|
||||
});
|
||||
|
||||
it("should use proxyBaseURL and server_root_path for /public/providers/fields when server_root_path is defined", async () => {
|
||||
const uiConfig = {
|
||||
server_root_path: "/api/v1",
|
||||
proxy_base_url: "https://example.com",
|
||||
};
|
||||
|
||||
const mockFetch = setupMockFetch([
|
||||
{ url: "/litellm/.well-known/litellm-ui-config", data: uiConfig },
|
||||
{ url: "/public/providers/fields", data: [] },
|
||||
]);
|
||||
|
||||
// First call getUiConfig to set up proxyBaseUrl
|
||||
await Networking.getUiConfig();
|
||||
|
||||
// Then call the public endpoint
|
||||
await Networking.getProviderCreateMetadata();
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledTimes(2);
|
||||
const publicEndpointCall = mockFetch.mock.calls.find((call) =>
|
||||
(call[0] as string).includes("/public/providers/fields"),
|
||||
);
|
||||
expect(publicEndpointCall).toBeDefined();
|
||||
const calledUrl = publicEndpointCall![0] as string;
|
||||
expect(calledUrl).toBe("https://example.com/api/v1/public/providers/fields");
|
||||
});
|
||||
|
||||
it("should use proxyBaseURL and server_root_path for /public/model_hub/info when server_root_path is defined", async () => {
|
||||
const uiConfig = {
|
||||
server_root_path: "/api/v1",
|
||||
proxy_base_url: "https://example.com",
|
||||
};
|
||||
|
||||
const mockFetch = setupMockFetch([
|
||||
{ url: "/litellm/.well-known/litellm-ui-config", data: uiConfig },
|
||||
{ url: "/public/model_hub/info", data: {} },
|
||||
]);
|
||||
|
||||
await Networking.getUiConfig();
|
||||
await Networking.getPublicModelHubInfo();
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledTimes(2);
|
||||
const publicEndpointCall = mockFetch.mock.calls.find((call) =>
|
||||
(call[0] as string).includes("/public/model_hub/info"),
|
||||
);
|
||||
expect(publicEndpointCall).toBeDefined();
|
||||
const calledUrl = publicEndpointCall![0] as string;
|
||||
expect(calledUrl).toBe("https://example.com/api/v1/public/model_hub/info");
|
||||
});
|
||||
|
||||
it("should use proxyBaseURL and server_root_path for /public/model_hub when server_root_path is defined", async () => {
|
||||
const uiConfig = {
|
||||
server_root_path: "/api/v1",
|
||||
proxy_base_url: "https://example.com",
|
||||
};
|
||||
|
||||
const mockFetch = setupMockFetch([
|
||||
{ url: "/litellm/.well-known/litellm-ui-config", data: uiConfig },
|
||||
{ url: "/public/model_hub", data: [] },
|
||||
]);
|
||||
|
||||
await Networking.getUiConfig();
|
||||
await Networking.modelHubPublicModelsCall();
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledTimes(2);
|
||||
const publicEndpointCall = mockFetch.mock.calls.find(
|
||||
(call) => (call[0] as string).includes("/public/model_hub") && !(call[0] as string).includes("/info"),
|
||||
);
|
||||
expect(publicEndpointCall).toBeDefined();
|
||||
const calledUrl = publicEndpointCall![0] as string;
|
||||
expect(calledUrl).toBe("https://example.com/api/v1/public/model_hub");
|
||||
});
|
||||
|
||||
it("should use proxyBaseURL and server_root_path for /public/agent_hub when server_root_path is defined", async () => {
|
||||
const uiConfig = {
|
||||
server_root_path: "/api/v1",
|
||||
proxy_base_url: "https://example.com",
|
||||
};
|
||||
|
||||
const mockFetch = setupMockFetch([
|
||||
{ url: "/litellm/.well-known/litellm-ui-config", data: uiConfig },
|
||||
{ url: "/public/agent_hub", data: [] },
|
||||
]);
|
||||
|
||||
await Networking.getUiConfig();
|
||||
await Networking.agentHubPublicModelsCall();
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledTimes(2);
|
||||
const publicEndpointCall = mockFetch.mock.calls.find((call) => (call[0] as string).includes("/public/agent_hub"));
|
||||
expect(publicEndpointCall).toBeDefined();
|
||||
const calledUrl = publicEndpointCall![0] as string;
|
||||
expect(calledUrl).toBe("https://example.com/api/v1/public/agent_hub");
|
||||
});
|
||||
|
||||
it("should use proxyBaseURL and server_root_path for /public/mcp_hub when server_root_path is defined", async () => {
|
||||
const uiConfig = {
|
||||
server_root_path: "/api/v1",
|
||||
proxy_base_url: "https://example.com",
|
||||
};
|
||||
|
||||
const mockFetch = setupMockFetch([
|
||||
{ url: "/litellm/.well-known/litellm-ui-config", data: uiConfig },
|
||||
{ url: "/public/mcp_hub", data: [] },
|
||||
]);
|
||||
|
||||
await Networking.getUiConfig();
|
||||
await Networking.mcpHubPublicServersCall();
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledTimes(2);
|
||||
const publicEndpointCall = mockFetch.mock.calls.find((call) => (call[0] as string).includes("/public/mcp_hub"));
|
||||
expect(publicEndpointCall).toBeDefined();
|
||||
const calledUrl = publicEndpointCall![0] as string;
|
||||
expect(calledUrl).toBe("https://example.com/api/v1/public/mcp_hub");
|
||||
});
|
||||
|
||||
it("should not include server_root_path when it is root path", async () => {
|
||||
const uiConfig = {
|
||||
server_root_path: "/",
|
||||
proxy_base_url: "https://example.com",
|
||||
};
|
||||
|
||||
const mockFetch = setupMockFetch([
|
||||
{ url: "/litellm/.well-known/litellm-ui-config", data: uiConfig },
|
||||
{ url: "/public/providers/fields", data: [] },
|
||||
]);
|
||||
|
||||
await Networking.getUiConfig();
|
||||
await Networking.getProviderCreateMetadata();
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledTimes(2);
|
||||
const publicEndpointCall = mockFetch.mock.calls.find((call) =>
|
||||
(call[0] as string).includes("/public/providers/fields"),
|
||||
);
|
||||
expect(publicEndpointCall).toBeDefined();
|
||||
const calledUrl = publicEndpointCall![0] as string;
|
||||
expect(calledUrl).toBe("https://example.com/public/providers/fields");
|
||||
});
|
||||
|
||||
it("should return UI config from getUiConfig", async () => {
|
||||
const uiConfig = {
|
||||
server_root_path: "/api/v1",
|
||||
proxy_base_url: "https://example.com",
|
||||
};
|
||||
|
||||
const mockFetch = setupMockFetch([{ url: "/litellm/.well-known/litellm-ui-config", data: uiConfig }]);
|
||||
|
||||
const result = await Networking.getUiConfig();
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledOnce();
|
||||
expect(result).toEqual(uiConfig);
|
||||
const configCall = mockFetch.mock.calls.find((call) =>
|
||||
(call[0] as string).includes("/litellm/.well-known/litellm-ui-config"),
|
||||
);
|
||||
expect(configCall).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ const handleError = async (errorData: string | any) => {
|
|||
if (currentTime - lastErrorTime > 60000) {
|
||||
// 60000 milliseconds = 60 seconds
|
||||
// Convert errorData to string if it isn't already
|
||||
const errorString = typeof errorData === 'string' ? errorData : JSON.stringify(errorData);
|
||||
const errorString = typeof errorData === "string" ? errorData : JSON.stringify(errorData);
|
||||
if (errorString.includes("Authentication Error - Expired Key")) {
|
||||
NotificationsManager.info("UI Session Expired. Logging out.");
|
||||
lastErrorTime = currentTime;
|
||||
|
|
@ -238,7 +238,7 @@ export const getProviderCreateMetadata = async (): Promise<ProviderCreateInfo[]>
|
|||
* Fetch provider credential field metadata from the proxy's public endpoint.
|
||||
* This is used by the UI to dynamically render provider-specific credential fields.
|
||||
*/
|
||||
const url = defaultProxyBaseUrl ? `${defaultProxyBaseUrl}/public/providers/fields` : `/public/providers/fields`;
|
||||
const url = proxyBaseUrl ? `${proxyBaseUrl}/public/providers/fields` : `/public/providers/fields`;
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
});
|
||||
|
|
@ -295,7 +295,7 @@ export const getUiConfig = async () => {
|
|||
};
|
||||
|
||||
export const getPublicModelHubInfo = async () => {
|
||||
const url = defaultProxyBaseUrl ? `${defaultProxyBaseUrl}/public/model_hub/info` : `/public/model_hub/info`;
|
||||
const url = proxyBaseUrl ? `${proxyBaseUrl}/public/model_hub/info` : `/public/model_hub/info`;
|
||||
const response = await fetch(url);
|
||||
const jsonData: PublicModelHubInfo = await response.json();
|
||||
return jsonData;
|
||||
|
|
@ -6749,7 +6749,6 @@ export const getGuardrailProviderSpecificParams = async (accessToken: string) =>
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
export const getAgentsList = async (accessToken: string) => {
|
||||
try {
|
||||
const url = proxyBaseUrl ? `${proxyBaseUrl}/v1/agents` : `/v1/agents`;
|
||||
|
|
@ -6867,7 +6866,6 @@ export const patchAgentCall = async (
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
export const updateGuardrailCall = async (
|
||||
accessToken: string,
|
||||
guardrailId: string,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue