fix(cliproxy): probe routing via management endpoint

This commit is contained in:
Tam Nhu Tran
2026-04-28 14:02:58 -04:00
parent 28a22a1b8a
commit 8ef703024b
4 changed files with 71 additions and 4 deletions
+3 -2
View File
@@ -20,6 +20,7 @@ import type { CliproxyRoutingStrategy } from './types';
/** Default timeout for management operations (longer than health check) */
const DEFAULT_TIMEOUT_MS = 5000;
const ROUTING_STRATEGY_PATH = '/v0/management/routing/strategy';
/** Default port for HTTPS protocol */
const DEFAULT_HTTPS_PORT = 443;
@@ -232,7 +233,7 @@ export class ManagementApiClient {
* Get the global credential routing strategy from CLIProxy.
*/
async getRoutingStrategy(): Promise<CliproxyRoutingStrategy> {
const response = await this.request<{ strategy?: string }>('GET', '/routing/strategy');
const response = await this.request<{ strategy?: string }>('GET', ROUTING_STRATEGY_PATH);
return response.data?.strategy === 'fill-first' ? 'fill-first' : 'round-robin';
}
@@ -240,7 +241,7 @@ export class ManagementApiClient {
* Update the global credential routing strategy on CLIProxy.
*/
async putRoutingStrategy(strategy: CliproxyRoutingStrategy): Promise<CliproxyRoutingStrategy> {
await this.request('PUT', '/routing/strategy', { value: strategy });
await this.request('PUT', ROUTING_STRATEGY_PATH, { value: strategy });
return strategy;
}
+2 -1
View File
@@ -7,13 +7,14 @@ import {
} from './proxy-target-resolver';
const ROUTING_TIMEOUT_MS = 5000;
const CLIPROXY_ROUTING_MANAGEMENT_PATH = '/v0/management/routing/strategy';
export async function fetchCliproxyRoutingResponse(
target: ProxyTarget,
method: 'GET' | 'PUT',
body?: Record<string, string>
): Promise<Response> {
const url = buildProxyUrl(target, '/routing/strategy');
const url = buildProxyUrl(target, CLIPROXY_ROUTING_MANAGEMENT_PATH);
const headers = buildManagementHeaders(
target,
body ? { 'Content-Type': 'application/json' } : {}
@@ -128,7 +128,7 @@ describe('management-api-client', () => {
expect(strategy).toBe('round-robin');
expect(fetchMock).toHaveBeenCalledWith(
'http://localhost:8317/routing/strategy',
'http://localhost:8317/v0/management/routing/strategy',
expect.objectContaining({
method: 'PUT',
body: JSON.stringify({ value: 'round-robin' }),
@@ -0,0 +1,65 @@
import { afterEach, describe, expect, it, mock } from 'bun:test';
import { fetchCliproxyRoutingResponse } from '../../../src/cliproxy/routing-strategy-http';
import type { ProxyTarget } from '../../../src/cliproxy/proxy-target-resolver';
describe('routing-strategy-http', () => {
const target: ProxyTarget = {
host: '127.0.0.1',
port: 8317,
protocol: 'http',
isRemote: false,
};
afterEach(() => {
mock.restore();
});
it('reads the routing strategy from the management endpoint', async () => {
const originalFetch = global.fetch;
const fetchMock = mock(() =>
Promise.resolve(
new Response(JSON.stringify({ strategy: 'round-robin' }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
})
)
);
global.fetch = fetchMock as typeof global.fetch;
await fetchCliproxyRoutingResponse(target, 'GET');
expect(fetchMock).toHaveBeenCalledWith(
'http://127.0.0.1:8317/v0/management/routing/strategy',
expect.objectContaining({
method: 'GET',
})
);
global.fetch = originalFetch;
});
it('writes the routing strategy to the management endpoint', async () => {
const originalFetch = global.fetch;
const fetchMock = mock(() =>
Promise.resolve(
new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
})
)
);
global.fetch = fetchMock as typeof global.fetch;
await fetchCliproxyRoutingResponse(target, 'PUT', { value: 'fill-first' });
expect(fetchMock).toHaveBeenCalledWith(
'http://127.0.0.1:8317/v0/management/routing/strategy',
expect.objectContaining({
method: 'PUT',
body: JSON.stringify({ value: 'fill-first' }),
})
);
global.fetch = originalFetch;
});
});