Skip to content

Commit 4651ead

Browse files
committed
fix fetch error
1 parent c7ee9ce commit 4651ead

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

src/api/cloudflare.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ export class CloudflareApi {
6666
private readonly fetcher: typeof fetch;
6767

6868
constructor(private readonly config: CloudflareApiConfig) {
69-
this.fetcher = config.fetcher ?? fetch;
69+
// Wrap fetch in arrow function to avoid "Illegal invocation" binding errors in Workers runtime
70+
this.fetcher = config.fetcher ?? ((...args) => fetch(...args));
7071
}
7172

7273
private get headers(): HeadersInit {

src/workflow.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export class MetricsExporterWorkflow extends WorkflowEntrypoint<Env> {
4848
);
4949
const id = jurisdiction.idFromName("metrics-proxy");
5050
const stub = jurisdiction.get(id);
51-
fetcher = stub.fetch.bind(stub);
51+
fetcher = (input, init) => stub.fetch(new Request(input, init));
5252
}
5353

5454
const cloudflare = createCloudflareApi(

test/cloudflare-api.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { describe, expect, it, vi } from "vitest";
2+
import { createCloudflareApi } from "../src/api/cloudflare";
3+
4+
describe("CloudflareApi", () => {
5+
describe("fetcher binding", () => {
6+
it("uses global fetch without binding errors when no custom fetcher provided", async () => {
7+
const mockFetch = vi.fn().mockResolvedValue(
8+
new Response(
9+
JSON.stringify({
10+
success: true,
11+
result: [],
12+
}),
13+
),
14+
);
15+
16+
// Temporarily replace global fetch
17+
const originalFetch = globalThis.fetch;
18+
globalThis.fetch = mockFetch;
19+
20+
try {
21+
const api = createCloudflareApi("test-account", "test-token");
22+
await api.listContainers();
23+
24+
expect(mockFetch).toHaveBeenCalledTimes(1);
25+
} finally {
26+
globalThis.fetch = originalFetch;
27+
}
28+
});
29+
30+
it("uses custom fetcher when provided", async () => {
31+
const customFetcher = vi.fn().mockResolvedValue(
32+
new Response(
33+
JSON.stringify({
34+
success: true,
35+
result: [],
36+
}),
37+
),
38+
);
39+
40+
const api = createCloudflareApi(
41+
"test-account",
42+
"test-token",
43+
customFetcher,
44+
);
45+
await api.listContainers();
46+
47+
expect(customFetcher).toHaveBeenCalledTimes(1);
48+
expect(customFetcher).toHaveBeenCalledWith(
49+
"https://api.cloudflare.com/client/v4/accounts/test-account/containers/applications",
50+
expect.objectContaining({
51+
headers: expect.objectContaining({
52+
Authorization: "Bearer test-token",
53+
}),
54+
}),
55+
);
56+
});
57+
});
58+
});

0 commit comments

Comments
 (0)