import { AssetWorkerInner } from "@cloudflare/workers-shared/asset-worker"; import { normalizeConfiguration } from "@cloudflare/workers-shared/asset-worker/src/configuration"; import { getAssetWithMetadataFromKV } from "@cloudflare/workers-shared/asset-worker/src/utils/kv"; import { SELF } from "cloudflare:test"; import { afterEach, beforeEach, describe, it, vi } from "vitest"; import type { AssetMetadata } from "@cloudflare/workers-shared/asset-worker/src/utils/kv"; const IncomingRequest = Request; vi.mock("@cloudflare/workers-shared/asset-worker/src/utils/kv.ts"); vi.mock("@cloudflare/workers-shared/asset-worker/src/configuration"); const existsMock = (fileList: Set) => { const mockImplementation = async (pathname: string) => { if (fileList.has(pathname)) { return pathname; } return null; }; vi.spyOn(AssetWorkerInner.prototype, "unstable_exists").mockImplementation( mockImplementation ); }; const BASE_URL = "http://example.com"; describe("[Asset Worker] `test slash normalization`", () => { afterEach(() => { vi.restoreAllMocks(); vi.mocked(getAssetWithMetadataFromKV).mockReset(); }); beforeEach(async () => { vi.mocked(getAssetWithMetadataFromKV).mockImplementation( () => Promise.resolve({ value: "no-op", metadata: { contentType: "no-op", }, }) as unknown as Promise< KVNamespaceGetWithMetadataResult > ); const originalApplyConfigurationDefaults = ( await vi.importActual< typeof import("@cloudflare/workers-shared/asset-worker/src/configuration") >("@cloudflare/workers-shared/asset-worker/src/configuration") ).normalizeConfiguration; vi.mocked(normalizeConfiguration).mockImplementation(() => ({ ...originalApplyConfigurationDefaults({}), html_handling: "none", not_found_handling: "none", })); }); it("returns 200 leading encoded double slash", async ({ expect }) => { const files = ["/blog/index.html"]; const requestPath = "/%2fblog/index.html"; existsMock(new Set(files)); const request = new IncomingRequest(BASE_URL + requestPath); let response = await SELF.fetch(request); expect(response.status).toBe(200); }); it("returns 200 leading non encoded double slash", async ({ expect }) => { const files = ["/blog/index.html"]; const requestPath = "//blog/index.html"; existsMock(new Set(files)); const request = new IncomingRequest(BASE_URL + requestPath); let response = await SELF.fetch(request); expect(response.status).toBe(200); }); it("returns 404 for non matched url", async ({ expect }) => { const files = ["/blog/index.html"]; const requestPath = "/%2fexample.com/"; existsMock(new Set(files)); const request = new IncomingRequest(BASE_URL + requestPath); let response = await SELF.fetch(request); expect(response.status).toBe(404); }); });