mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-30 18:33:35 +00:00
fix(microsoft-foundry): bound connection test error reads (#97812)
Co-authored-by: Pick-cat <266665499+Pick-cat@users.noreply.github.com>
This commit is contained in:
73
extensions/microsoft-foundry/onboard.connection.test.ts
Normal file
73
extensions/microsoft-foundry/onboard.connection.test.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
// Microsoft Foundry tests cover bounded connection-test error reads.
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import * as cli from "./cli.js";
|
||||
import { testFoundryConnection } from "./onboard.js";
|
||||
import { DEFAULT_API } from "./shared.js";
|
||||
|
||||
const hoisted = vi.hoisted(() => ({
|
||||
fetchWithSsrFGuard: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/ssrf-runtime", () => ({
|
||||
fetchWithSsrFGuard: hoisted.fetchWithSsrFGuard,
|
||||
}));
|
||||
|
||||
function cancelTrackedResponse(
|
||||
text: string,
|
||||
init: ResponseInit,
|
||||
): {
|
||||
response: Response;
|
||||
wasCanceled: () => boolean;
|
||||
} {
|
||||
let canceled = false;
|
||||
const stream = new ReadableStream<Uint8Array>({
|
||||
start(controller) {
|
||||
controller.enqueue(new TextEncoder().encode(text));
|
||||
},
|
||||
cancel() {
|
||||
canceled = true;
|
||||
},
|
||||
});
|
||||
return {
|
||||
response: new Response(stream, init),
|
||||
wasCanceled: () => canceled,
|
||||
};
|
||||
}
|
||||
|
||||
describe("testFoundryConnection", () => {
|
||||
beforeEach(() => {
|
||||
vi.spyOn(cli, "getAccessTokenResult").mockReturnValue({ accessToken: "token" });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
hoisted.fetchWithSsrFGuard.mockReset();
|
||||
});
|
||||
|
||||
it("bounds connection-test error bodies without using response.text()", async () => {
|
||||
const note = vi.fn();
|
||||
const tracked = cancelTrackedResponse(`${"foundry failure ".repeat(1024)}tail`, {
|
||||
status: 503,
|
||||
headers: { "content-type": "text/plain" },
|
||||
});
|
||||
const textSpy = vi.spyOn(tracked.response, "text").mockRejectedValue(new Error("unbounded"));
|
||||
hoisted.fetchWithSsrFGuard.mockResolvedValue({
|
||||
response: tracked.response,
|
||||
release: async () => {},
|
||||
});
|
||||
|
||||
await testFoundryConnection({
|
||||
ctx: { prompter: { note } } as never,
|
||||
endpoint: "https://example.openai.azure.com",
|
||||
modelId: "gpt-4o",
|
||||
api: DEFAULT_API,
|
||||
});
|
||||
|
||||
expect(textSpy).not.toHaveBeenCalled();
|
||||
expect(tracked.wasCanceled()).toBe(true);
|
||||
expect(note).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Warning: test request returned 503"),
|
||||
"Connection Test",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
// Microsoft Foundry setup module handles plugin onboarding behavior.
|
||||
import type { ProviderAuthContext } from "openclaw/plugin-sdk/core";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
|
||||
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
import {
|
||||
normalizeOptionalString,
|
||||
@@ -32,6 +33,8 @@ import {
|
||||
usesFoundryResponsesByDefault,
|
||||
} from "./shared.js";
|
||||
|
||||
const FOUNDRY_CONNECTION_TEST_ERROR_BODY_LIMIT_BYTES = 8 * 1024;
|
||||
|
||||
export { listSubscriptions } from "./cli.js";
|
||||
|
||||
function listFoundryResources(subscriptionId?: string): FoundryResourceOption[] {
|
||||
@@ -605,13 +608,19 @@ export async function testFoundryConnection(params: {
|
||||
});
|
||||
try {
|
||||
if (res.status === 400) {
|
||||
const body = await res.text().catch(() => "");
|
||||
const body = await readResponseTextLimited(
|
||||
res,
|
||||
FOUNDRY_CONNECTION_TEST_ERROR_BODY_LIMIT_BYTES,
|
||||
).catch(() => "");
|
||||
await params.ctx.prompter.note(
|
||||
`Endpoint is reachable but returned 400 Bad Request - check your deployment name and API version.\n${body.slice(0, 200)}`,
|
||||
"Connection Test",
|
||||
);
|
||||
} else if (!res.ok) {
|
||||
const body = await res.text().catch(() => "");
|
||||
const body = await readResponseTextLimited(
|
||||
res,
|
||||
FOUNDRY_CONNECTION_TEST_ERROR_BODY_LIMIT_BYTES,
|
||||
).catch(() => "");
|
||||
await params.ctx.prompter.note(
|
||||
`Warning: test request returned ${res.status}. ${body.slice(0, 200)}\nProceeding anyway - you can fix the endpoint later.`,
|
||||
"Connection Test",
|
||||
|
||||
Reference in New Issue
Block a user