mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-30 19:59:35 +00:00
fix(zalo): cap api request timeouts
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const resolvePinnedHostnameWithPolicyMock = vi.fn();
|
||||
const { resolvePinnedHostnameWithPolicyMock } = vi.hoisted(() => ({
|
||||
resolvePinnedHostnameWithPolicyMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/ssrf-runtime", () => ({
|
||||
resolvePinnedHostnameWithPolicy: (...args: unknown[]) =>
|
||||
@@ -9,6 +11,8 @@ vi.mock("openclaw/plugin-sdk/ssrf-runtime", () => ({
|
||||
|
||||
import { deleteWebhook, getWebhookInfo, sendChatAction, sendPhoto, type ZaloFetch } from "./api.js";
|
||||
|
||||
const MAX_TIMER_TIMEOUT_MS = 2_147_000_000;
|
||||
|
||||
function createOkFetcher() {
|
||||
return vi.fn<ZaloFetch>(async () => new Response(JSON.stringify({ ok: true, result: {} })));
|
||||
}
|
||||
@@ -90,6 +94,38 @@ describe("Zalo API request methods", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("caps oversized sendChatAction timeouts before scheduling the timer", async () => {
|
||||
const setTimeoutMock = vi
|
||||
.spyOn(globalThis, "setTimeout")
|
||||
.mockImplementation((() => 1) as typeof setTimeout);
|
||||
const clearTimeoutMock = vi
|
||||
.spyOn(globalThis, "clearTimeout")
|
||||
.mockImplementation(() => undefined);
|
||||
try {
|
||||
const fetcher = vi.fn<ZaloFetch>(
|
||||
async () =>
|
||||
({
|
||||
json: async () => ({ ok: true, result: {} }),
|
||||
}) as Response,
|
||||
);
|
||||
|
||||
await sendChatAction(
|
||||
"test-token",
|
||||
{
|
||||
chat_id: "chat-123",
|
||||
action: "typing",
|
||||
},
|
||||
fetcher,
|
||||
MAX_TIMER_TIMEOUT_MS + 1_000_000,
|
||||
);
|
||||
|
||||
expect(setTimeoutMock).toHaveBeenCalledWith(expect.any(Function), MAX_TIMER_TIMEOUT_MS);
|
||||
} finally {
|
||||
setTimeoutMock.mockRestore();
|
||||
clearTimeoutMock.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it("validates outbound photo URLs against the SSRF guard before posting", async () => {
|
||||
const fetcher = createOkFetcher();
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @see https://bot.zaloplatforms.com/docs
|
||||
*/
|
||||
|
||||
import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
||||
import { resolvePinnedHostnameWithPolicy, type SsrFPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
|
||||
const ZALO_API_BASE = "https://bot-api.zaloplatforms.com";
|
||||
@@ -112,9 +113,12 @@ export async function callZaloApi<T = unknown>(
|
||||
): Promise<ZaloApiResponse<T>> {
|
||||
const url = `${ZALO_API_BASE}/bot${token}/${method}`;
|
||||
const controller = new AbortController();
|
||||
const timeoutId = options?.timeoutMs
|
||||
? setTimeout(() => controller.abort(), options.timeoutMs)
|
||||
: undefined;
|
||||
const requestTimeoutMs =
|
||||
options?.timeoutMs === undefined ? undefined : resolveTimerTimeoutMs(options.timeoutMs, 1);
|
||||
const timeoutId =
|
||||
requestTimeoutMs === undefined
|
||||
? undefined
|
||||
: setTimeout(() => controller.abort(), requestTimeoutMs);
|
||||
const fetcher = options?.fetch ?? fetch;
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user