mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 11:01:34 +00:00
* fix(elevenlabs): fall back to default base URL when config value is malformed * fix(elevenlabs): reject malformed and non-http(s) base URL overrides * fix(elevenlabs): redact configured URL from base URL validation errors * fix(elevenlabs): preserve realtime WebSocket overrides * test(elevenlabs): avoid stale realtime test overlap * style(elevenlabs): format realtime URL assertion --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
78 lines
3.4 KiB
TypeScript
78 lines
3.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
DEFAULT_ELEVENLABS_BASE_URL,
|
|
normalizeElevenLabsBaseUrl,
|
|
normalizeElevenLabsRealtimeBaseUrl,
|
|
} from "./shared.js";
|
|
|
|
describe("normalizeElevenLabsBaseUrl", () => {
|
|
it("returns the default when the base URL is missing or blank", () => {
|
|
expect(normalizeElevenLabsBaseUrl(undefined)).toBe(DEFAULT_ELEVENLABS_BASE_URL);
|
|
expect(normalizeElevenLabsBaseUrl(" ")).toBe(DEFAULT_ELEVENLABS_BASE_URL);
|
|
});
|
|
|
|
it("trims and strips trailing slashes from a valid URL", () => {
|
|
expect(normalizeElevenLabsBaseUrl(" https://custom.example.com/ ")).toBe(
|
|
"https://custom.example.com",
|
|
);
|
|
expect(normalizeElevenLabsBaseUrl("http://localhost:8080")).toBe("http://localhost:8080");
|
|
});
|
|
|
|
it("rejects an explicit malformed override instead of silently retargeting", () => {
|
|
// An operator's explicit endpoint must not be swapped for the default; fail
|
|
// actionably here so the request cannot target an unintended host, and so a
|
|
// downstream `new URL(...)` never throws an opaque TypeError.
|
|
expect(() => normalizeElevenLabsBaseUrl("not a url")).toThrow(/Invalid ElevenLabs baseUrl/);
|
|
expect(() => normalizeElevenLabsBaseUrl("////")).toThrow(/Invalid ElevenLabs baseUrl/);
|
|
});
|
|
|
|
it("rejects a parseable but unsupported (non-HTTP(S)) scheme", () => {
|
|
// `new URL()` accepts ftp:/data:/custom schemes, but downstream fetch and
|
|
// WebSocket paths only support http(s) ElevenLabs endpoints.
|
|
expect(() => normalizeElevenLabsBaseUrl("ftp://files.example.com")).toThrow(
|
|
/unsupported scheme/,
|
|
);
|
|
expect(() => normalizeElevenLabsBaseUrl("data:text/plain,x")).toThrow(/unsupported scheme/);
|
|
});
|
|
|
|
it("does not leak URL credentials or sensitive query values in validation errors", () => {
|
|
// Rejection errors may reach logs/diagnostics; they must not echo userinfo
|
|
// or credential-bearing query parameters from the configured baseUrl.
|
|
const nonHttp = "ftp://user:sup3r-secret@files.example.com/x?api_key=leak-me";
|
|
expect(() => normalizeElevenLabsBaseUrl(nonHttp)).toThrow(/unsupported scheme/);
|
|
try {
|
|
normalizeElevenLabsBaseUrl(nonHttp);
|
|
} catch (error) {
|
|
const message = (error as Error).message;
|
|
expect(message).not.toContain("sup3r-secret");
|
|
expect(message).not.toContain("leak-me");
|
|
expect(message).not.toContain("api_key");
|
|
}
|
|
// A malformed value that embeds a token must not be echoed either.
|
|
const malformed = "http://:not a url token=abcd1234secret";
|
|
try {
|
|
normalizeElevenLabsBaseUrl(malformed);
|
|
} catch (error) {
|
|
expect((error as Error).message).not.toContain("abcd1234secret");
|
|
}
|
|
});
|
|
|
|
it("keeps every accepted result parseable as an http(s) URL", () => {
|
|
for (const input of ["https://ok.example.com/", "http://a.b:9000"]) {
|
|
const normalized = normalizeElevenLabsBaseUrl(input);
|
|
const url = new URL(normalized);
|
|
expect(["http:", "https:"]).toContain(url.protocol);
|
|
}
|
|
});
|
|
|
|
it("maps HTTP endpoints and preserves explicit WebSocket endpoints for realtime", () => {
|
|
expect(normalizeElevenLabsRealtimeBaseUrl("https://api.example.com/")).toBe(
|
|
"wss://api.example.com",
|
|
);
|
|
expect(normalizeElevenLabsRealtimeBaseUrl("wss://realtime.example.com/")).toBe(
|
|
"wss://realtime.example.com",
|
|
);
|
|
expect(normalizeElevenLabsRealtimeBaseUrl("ws://localhost:8080/")).toBe("ws://localhost:8080");
|
|
});
|
|
});
|