diff --git a/workers/controller/src/index.ts b/workers/controller/src/index.ts index a63299c..b75d471 100644 --- a/workers/controller/src/index.ts +++ b/workers/controller/src/index.ts @@ -61,6 +61,17 @@ async function handlePurgeRequest( ); } + const { data } = Purge.safeParse(await request.json()); + if (!data) { + return Response.json( + { + error: "Malformed request", + }, + { status: 400 }, + ); + } + const { tags } = data; + const client = new Cloudflare({ apiToken: token, }); @@ -76,7 +87,6 @@ async function handlePurgeRequest( ); } - const { tags } = Purge.parse(await request.json()); console.debug("[Cache Purge Request] Purge Tags", tags); // If no zone is present, then all zones will be purged. diff --git a/workers/controller/test/purge.spec.ts b/workers/controller/test/purge.spec.ts index 55d1573..d1be02f 100644 --- a/workers/controller/test/purge.spec.ts +++ b/workers/controller/test/purge.spec.ts @@ -1,5 +1,5 @@ import { SELF, env } from "cloudflare:test"; -import { it, expect, vi } from "vitest"; +import { it, expect, vi, afterEach } from "vitest"; import type Cloudflare from "cloudflare"; const verify = vi.fn< @@ -17,6 +17,10 @@ vi.mock("cloudflare", () => ({ })), })); +afterEach(() => { + vi.clearAllMocks(); +}); + it("adds cache tags to the purge queue", async () => { verify.mockResolvedValueOnce({ status: "active", id: "foo" }); @@ -85,3 +89,64 @@ it("adds cache tags to the purge queue with no zone", async () => { }, ]); }); + +it("returns a 401 when the wrong API Token is provided", async () => { + const response = await SELF.fetch( + "https://cache-tag.example.workers.dev/purge", + { + method: "POST", + body: JSON.stringify({ + tags: ["test"], + }), + headers: { + Authorization: `Bearer wrong`, + "CF-Worker": "example.com", + }, + }, + ); + + expect(response.status).toBe(401); + + expect(verify).not.toBeCalled(); +}); + +it("returns a 401 when the wrong API Token is expired", async () => { + verify.mockResolvedValueOnce({ status: "expired", id: "foo" }); + + const response = await SELF.fetch( + "https://cache-tag.example.workers.dev/purge", + { + method: "POST", + body: JSON.stringify({ + tags: ["test"], + }), + headers: { + Authorization: `Bearer ${env.API_TOKEN}`, + }, + }, + ); + + expect(response.status).toBe(401); + + expect(verify).toBeCalled(); +}); + +it("returns a 400 when request is malformed", async () => { + const response = await SELF.fetch( + "https://cache-tag.example.workers.dev/purge", + { + method: "POST", + body: JSON.stringify({ + url: "https://example.com", + }), + headers: { + Authorization: `Bearer ${env.API_TOKEN}`, + "CF-Worker": "example.com", + }, + }, + ); + + expect(response.status).toBe(400); + + expect(verify).not.toBeCalled(); +});