diff --git a/fixtures/asset-config/html-handling.test.ts b/fixtures/asset-config/html-handling.test.ts index 274d69b0b574..e024bfd956cc 100644 --- a/fixtures/asset-config/html-handling.test.ts +++ b/fixtures/asset-config/html-handling.test.ts @@ -3,6 +3,8 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { applyConfigurationDefaults } from "../../packages/workers-shared/asset-worker/src/configuration"; import Worker from "../../packages/workers-shared/asset-worker/src/index"; import { getAssetWithMetadataFromKV } from "../../packages/workers-shared/asset-worker/src/utils/kv"; +import { encodingTestCases } from "./test-cases/encoding-test-cases"; +import { htmlHandlingTestCases } from "./test-cases/html-handling-test-cases"; import type { AssetMetadata } from "../../packages/workers-shared/asset-worker/src/utils/kv"; const IncomingRequest = Request; @@ -20,7 +22,7 @@ const existsMock = (fileList: Set) => { }; const BASE_URL = "http://example.com"; -type TestCase = { +export type TestCase = { title: string; files: string[]; requestPath: string; @@ -28,756 +30,18 @@ type TestCase = { finalPath?: string; }; -const testCases: { - html_handling: - | "auto-trailing-slash" - | "drop-trailing-slash" - | "force-trailing-slash" - | "none"; - cases: TestCase[]; -}[] = [ +const testSuites = [ { - html_handling: "auto-trailing-slash", - cases: [ - { - title: "/ -> 200 (with /index.html)", - files: ["/index.html"], - requestPath: "/index.html", - matchedFile: "/index.html", - finalPath: "/", - }, - { - title: "/index -> / 307 (with /index.html)", - files: ["/index.html"], - requestPath: "/index", - matchedFile: "/index.html", - finalPath: "/", - }, - { - title: "/index.html -> / 307 (with /index.html)", - files: ["/index.html"], - requestPath: "/index.html", - matchedFile: "/index.html", - finalPath: "/", - }, - { - title: "/both -> 200 (with /both.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both", - matchedFile: "/both.html", - finalPath: "/both", - }, - { - title: "/both.html -> /both 307 (with /both.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both.html", - matchedFile: "/both.html", - finalPath: "/both", - }, - { - title: "/both/ -> 200 (with /both/index.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both/", - matchedFile: "/both/index.html", - finalPath: "/both/", - }, - { - title: "/both/index.html -> /both/ 307 (with /both/index.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both/index.html", - matchedFile: "/both/index.html", - finalPath: "/both/", - }, - { - title: "/both/index -> /both/ 307 (with /both/index.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both/index", - matchedFile: "/both/index.html", - finalPath: "/both/", - }, - { - title: "/file -> 200 (with file.html)", - files: ["/file.html"], - requestPath: "/file", - matchedFile: "/file.html", - finalPath: "/file", - }, - { - title: "/file.html -> /file 307 (with file.html)", - files: ["/file.html"], - requestPath: "/file.html", - matchedFile: "/file.html", - finalPath: "/file", - }, - { - title: "/file/ -> /file 307 (with file.html)", - files: ["/file.html"], - requestPath: "/file/", - matchedFile: "/file.html", - finalPath: "/file", - }, - { - title: "/file/index -> /file 307 (with file.html)", - files: ["/file.html"], - requestPath: "/file/index", - matchedFile: "/file.html", - finalPath: "/file", - }, - { - title: "/file/index.html -> /file 307 (with file.html)", - files: ["/file.html"], - requestPath: "/file/index.html", - matchedFile: "/file.html", - finalPath: "/file", - }, - { - title: "/folder -> /folder/ 307 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder", - matchedFile: "/folder/index.html", - finalPath: "/folder/", - }, - { - title: "/folder.html -> /folder/ 307 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder.html", - matchedFile: "/folder/index.html", - finalPath: "/folder/", - }, - { - title: "/folder/ -> 200 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder/", - matchedFile: "/folder/index.html", - finalPath: "/folder/", - }, - { - title: "/folder/index -> /folder/ 307 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder/index", - matchedFile: "/folder/index.html", - finalPath: "/folder/", - }, - { - title: "/folder/index.html -> /folder/ 307 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder/index.html", - matchedFile: "/folder/index.html", - finalPath: "/folder/", - }, - { - title: "/bin -> /bin/ 307 (with /bin/index.html)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin", - matchedFile: "/bin/index.html", - finalPath: "/bin/", - }, - { - title: "/bin.html -> /bin/ 307 (with /bin/index.html)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin.html", - matchedFile: "/bin/index.html", - finalPath: "/bin/", - }, - { - title: "/bin%2F -> 200 (with /bin%2F)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin%2F", - matchedFile: "/bin%2F", - finalPath: "/bin%2F", - }, - { - title: "/bin/ -> 200 (with /bin/index.html not /bin%2F", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin/", - matchedFile: "/bin/index.html", - finalPath: "/bin/", - }, - { - title: "/bin/index -> 307 /bin/ (with /bin/index.html)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin/index", - matchedFile: "/bin/index.html", - finalPath: "/bin/", - }, - { - title: "/bin/index.html -> 307 /bin/ (with /bin/index.html)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin/index.html", - matchedFile: "/bin/index.html", - finalPath: "/bin/", - }, - // prefers exact match - { - title: "/file-bin -> 200 ", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin", - matchedFile: "/file-bin", - finalPath: "/file-bin", - }, - // (doesn't rewrite if resulting path would match another asset) - { - title: "/file-bin.html -> 200 ", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin.html", - matchedFile: "/file-bin.html", - finalPath: "/file-bin.html", - }, - // (finds file-bin.html --rewrite--> /file-bin, but /file-bin exists) - { - title: "/file-bin/ -> 404 ", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin/", - }, - { - title: "/file-bin/index -> 404 ", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin/index", - }, - { - title: "/file-bin/index.html -> 404 ", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin/index.html", - }, - ], + title: "htmlHanding options", + suite: htmlHandlingTestCases, }, { - html_handling: "drop-trailing-slash", - cases: [ - // note that we don't drop the "/" if that is the only path component - { - title: "/ -> 200 (with /index.html)", - files: ["/index.html"], - requestPath: "/index.html", - matchedFile: "/index.html", - finalPath: "/", - }, - { - title: "/index -> / 307 (with /index.html)", - files: ["/index.html"], - requestPath: "/index", - matchedFile: "/index.html", - finalPath: "/", - }, - { - title: "/index.html -> / 307 (with /index.html)", - files: ["/index.html"], - requestPath: "/index.html", - matchedFile: "/index.html", - finalPath: "/", - }, - { - title: "/both -> 200 (with /both.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both", - matchedFile: "/both.html", - finalPath: "/both", - }, - { - title: "/both.html -> /both 307 (with /both.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both.html", - matchedFile: "/both.html", - finalPath: "/both", - }, - // drops trailing slash and so it tries /both.html first - { - title: "/both/ -> /both 307 (with /both.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both/", - matchedFile: "/both.html", - finalPath: "/both", - }, - { - title: "/both/index -> 307 (with /both.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both/index", - matchedFile: "/both.html", - finalPath: "/both", - }, - // can't rewrite /both/index.html: would be /both/ -> /both -> /both.html - // ie can only access /both/index.html by exact match - { - title: "/both/index.html -> 200 (with /both/index.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both/index.html", - matchedFile: "/both/index.html", - finalPath: "/both/index.html", - }, - { - title: "/file -> 200 (with file.html)", - files: ["/file.html"], - requestPath: "/file", - matchedFile: "/file.html", - finalPath: "/file", - }, - { - title: "/file.html -> /file 307 (with file.html)", - files: ["/file.html"], - requestPath: "/file.html", - matchedFile: "/file.html", - finalPath: "/file", - }, - { - title: "/file/ -> /file 307 (with file.html)", - files: ["/file.html"], - requestPath: "/file/", - matchedFile: "/file.html", - finalPath: "/file", - }, - { - title: "/file/index -> /file 307 (with file.html)", - files: ["/file.html"], - requestPath: "/file/index", - matchedFile: "/file.html", - finalPath: "/file", - }, - { - title: "/file/index.html -> /file 307 (with file.html)", - files: ["/file.html"], - requestPath: "/file/index.html", - matchedFile: "/file.html", - finalPath: "/file", - }, - { - title: "/folder -> 200 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder", - matchedFile: "/folder/index.html", - finalPath: "/folder", - }, - { - title: "/folder.html -> /folder 307 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder.html", - matchedFile: "/folder/index.html", - finalPath: "/folder", - }, - { - title: "/folder/ -> /folder 307 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder/", - matchedFile: "/folder/index.html", - finalPath: "/folder", - }, - { - title: "/folder/index -> /folder 307 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder/index", - matchedFile: "/folder/index.html", - finalPath: "/folder", - }, - { - title: "/folder/index.html -> /folder 307 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder/index.html", - matchedFile: "/folder/index.html", - finalPath: "/folder", - }, - { - title: "/bin -> 200 (with /bin/index.html)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin", - matchedFile: "/bin/index.html", - finalPath: "/bin", - }, - { - title: "/bin.html -> /bin 307 (with /bin/index.html)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin.html", - matchedFile: "/bin/index.html", - finalPath: "/bin", - }, - { - title: "/bin%2F -> 200 (with /bin%2F)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin%2F", - matchedFile: "/bin%2F", - finalPath: "/bin%2F", - }, - { - title: "/bin/ -> /bin 307 (with /bin/index.html not /bin%2F", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin/", - matchedFile: "/bin/index.html", - finalPath: "/bin", - }, - { - title: "/bin/index -> /bin 307 (with /bin/index.html not /bin%2F", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin/index", - matchedFile: "/bin/index.html", - finalPath: "/bin", - }, - { - title: "/bin/index.html -> /bin 307 (with /bin/index.html not /bin%2F", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin/index.html", - matchedFile: "/bin/index.html", - finalPath: "/bin", - }, - { - title: "/file-bin -> 200", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin", - matchedFile: "/file-bin", - finalPath: "/file-bin", - }, - // doesn't redirect to /file-bin because that also exists - { - title: "/file-bin.html -> 200 (with /file-bin.html)", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin.html", - matchedFile: "/file-bin.html", - finalPath: "/file-bin.html", - }, - // 404s because ambiguity between /file-bin or /file-bin.html? - { - title: "/file-bin/ -> 404", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin/", - }, - { - title: "/file-bin/index -> 404", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin/index", - }, - { - title: "/file-bin/index.html -> 404", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin/index.html", - }, - ], - }, - { - html_handling: "force-trailing-slash", - cases: [ - { - title: "/ -> 200 (with /index.html)", - files: ["/index.html"], - requestPath: "/index.html", - matchedFile: "/index.html", - finalPath: "/", - }, - { - title: "/index -> / 307 (with /index.html)", - files: ["/index.html"], - requestPath: "/index", - matchedFile: "/index.html", - finalPath: "/", - }, - { - title: "/index.html -> / 307 (with /index.html)", - files: ["/index.html"], - requestPath: "/index.html", - matchedFile: "/index.html", - finalPath: "/", - }, - // ie tries /both/index.html first - { - title: "/both -> /both/ 307 (with /both/index.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both", - matchedFile: "/both/index.html", - finalPath: "/both/", - }, - // can't rewrite /both.html: would be /both -> /both/ -> /both/index.html - // ie can only access /both.html by exact match - { - title: "/both.html -> 200", - files: ["/both.html", "/both/index.html"], - requestPath: "/both.html", - matchedFile: "/both.html", - finalPath: "/both.html", - }, - { - title: "/both/ -> 200 (with /both/index.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both/", - matchedFile: "/both/index.html", - finalPath: "/both/", - }, - { - title: "/both/index -> /both/ 307 (with /both/index.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both/index", - matchedFile: "/both/index.html", - finalPath: "/both/", - }, - { - title: "/both/index.html -> /both/ 307 (with /both/index.html)", - files: ["/both.html", "/both/index.html"], - requestPath: "/both/index.html", - matchedFile: "/both/index.html", - finalPath: "/both/", - }, - // always ends in a trailing slash - { - title: "/file -> /file/ 307 (with file.html)", - files: ["/file.html"], - requestPath: "/file", - matchedFile: "/file.html", - finalPath: "/file/", - }, - { - title: "/file.html -> /file/ 307 (with file.html)", - files: ["/file.html"], - requestPath: "/file.html", - matchedFile: "/file.html", - finalPath: "/file/", - }, - - { - title: "/file/ -> 200 (with file.html)", - files: ["/file.html"], - requestPath: "/file/", - matchedFile: "/file.html", - finalPath: "/file/", - }, - { - title: "/file/index -> /file/ 307 (with file.html)", - files: ["/file.html"], - requestPath: "/file/index", - matchedFile: "/file.html", - finalPath: "/file/", - }, - { - title: "/file/index.html -> /file/ 307 (with file.html)", - files: ["/file.html"], - requestPath: "/file/index.html", - matchedFile: "/file.html", - finalPath: "/file/", - }, - { - title: "/folder -> /folder/ 307 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder", - matchedFile: "/folder/index.html", - finalPath: "/folder/", - }, - { - title: "/folder.html -> /folder/ 307 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder.html", - matchedFile: "/folder/index.html", - finalPath: "/folder/", - }, - { - title: "/folder/ -> 200 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder/", - matchedFile: "/folder/index.html", - finalPath: "/folder/", - }, - { - title: "/folder/index -> /folder/ 307 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder/index", - matchedFile: "/folder/index.html", - finalPath: "/folder/", - }, - { - title: "/folder/index.html -> /folder/ 307 (with /folder/index.html)", - files: ["/folder/index.html"], - requestPath: "/folder/index.html", - matchedFile: "/folder/index.html", - finalPath: "/folder/", - }, - { - title: "/bin -> /bin/ 307 (with /bin/index.html)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin", - matchedFile: "/bin/index.html", - finalPath: "/bin/", - }, - { - title: "/bin.html -> /bin/ 307 (with /bin/index.html)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin.html", - matchedFile: "/bin/index.html", - finalPath: "/bin/", - }, - { - title: "/bin%2F -> 200 (with /bin%2F)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin%2F", - matchedFile: "/bin%2F", - finalPath: "/bin%2F", - }, - { - title: "/bin/ -> 200 (with /bin/index.html not /bin%2F", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin/", - matchedFile: "/bin/index.html", - finalPath: "/bin/", - }, - { - title: "/bin/index -> /bin/ 307 (with /bin/index.html)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin/index", - matchedFile: "/bin/index.html", - finalPath: "/bin/", - }, - { - title: "/bin/index.html -> /bin/ 307 (with /bin/index.html)", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin/index.html", - matchedFile: "/bin/index.html", - finalPath: "/bin/", - }, - // doesn't force a trailing slash here because it would redirect to /file-bin.html - { - title: "/file-bin -> 200", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin", - matchedFile: "/file-bin", - finalPath: "/file-bin", - }, - { - title: "/file-bin.html -> /file-bin/ 307 (with /file-bin.html)", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin.html", - matchedFile: "/file-bin.html", - finalPath: "/file-bin/", - }, - { - title: "/file-bin/ -> 200", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin/", - matchedFile: "/file-bin.html", - finalPath: "/file-bin/", - }, - { - title: "/file-bin/index -> /file-bin/ 307 (with /file-bin.html)", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin/index", - matchedFile: "/file-bin.html", - finalPath: "/file-bin/", - }, - { - title: "/file-bin/index.html -> /file-bin/ 307 (with /file-bin.html)", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin/index.html", - matchedFile: "/file-bin.html", - finalPath: "/file-bin/", - }, - ], - }, - { - html_handling: "none", - cases: [ - { - title: "/ -> 404", - files: ["/index.html"], - requestPath: "/", - }, - { - title: "/index -> 404", - files: ["/index.html"], - requestPath: "/index", - }, - { - title: "/index.html -> 200", - files: ["/index.html"], - requestPath: "/index.html", - matchedFile: "/index.html", - finalPath: "/index.html", - }, - { - title: "/both -> 404", - files: ["/both.html", "/both/index.html"], - requestPath: "/both", - }, - { - title: "/both.html -> 200", - files: ["/both.html", "/both/index.html"], - requestPath: "/both.html", - matchedFile: "/both.html", - finalPath: "/both.html", - }, - { - title: "/both/ -> 404", - files: ["/both.html", "/both/index.html"], - requestPath: "/both/", - }, - { - title: "/both/index.html -> 200", - files: ["/both.html", "/both/index.html"], - requestPath: "/both/index.html", - matchedFile: "/both/index.html", - finalPath: "/both/index.html", - }, - { - title: "/file/index.html -> 404", - files: ["/file.html"], - requestPath: "/file/index.html", - }, - { - title: "/folder.html -> 404", - files: ["/folder/index.html"], - requestPath: "/folder.html", - }, - { - title: "/bin -> 404", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin", - }, - { - title: "/bin.html -> 404", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin.html", - }, - { - title: "/bin%2F -> 200", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin%2F", - matchedFile: "/bin%2F", - finalPath: "/bin%2F", - }, - { - title: "/bin/ -> 404", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin/", - }, - { - title: "/bin/index -> 404", - files: ["/bin%2F", "/bin/index.html"], - requestPath: "/bin/index", - }, - { - title: "/file-bin -> 200", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin", - matchedFile: "/file-bin", - finalPath: "/file-bin", - }, - { - title: "/file-bin.html -> 200", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin.html", - matchedFile: "/file-bin.html", - finalPath: "/file-bin.html", - }, - { - title: "/file-bin/ -> 404", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin/", - }, - { - title: "/file-bin/index -> 404", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin/index", - }, - { - title: "/file-bin/index.html -> 404", - files: ["/file-bin", "/file-bin.html"], - requestPath: "/file-bin/index.html", - }, - ], + title: "encoding options", + suite: encodingTestCases, }, ]; -describe("htmlHanding options", () => { +describe.each(testSuites)("$title", ({ title, suite }) => { beforeEach(() => { vi.mocked(getAssetWithMetadataFromKV).mockImplementation( () => @@ -794,7 +58,7 @@ describe("htmlHanding options", () => { afterEach(() => { vi.mocked(getAssetWithMetadataFromKV).mockRestore(); }); - describe.each(testCases)(`$html_handling`, ({ html_handling, cases }) => { + describe.each(suite)(`$html_handling`, ({ html_handling, cases }) => { beforeEach(() => { vi.mocked(applyConfigurationDefaults).mockImplementation(() => { return { @@ -815,7 +79,6 @@ describe("htmlHanding options", () => { undefined, matchedFile ); - console.dir(response.status); expect(response.status).toBe(200); expect(response.url).toBe(BASE_URL + finalPath); // can't check intermediate 307 directly: diff --git a/fixtures/asset-config/test-cases/encoding-test-cases.ts b/fixtures/asset-config/test-cases/encoding-test-cases.ts new file mode 100644 index 000000000000..0da5719f1947 --- /dev/null +++ b/fixtures/asset-config/test-cases/encoding-test-cases.ts @@ -0,0 +1,631 @@ +import { TestCase } from "../html-handling.test"; + +export const encodingTestCases: { + html_handling: + | "auto-trailing-slash" + | "drop-trailing-slash" + | "force-trailing-slash" + | "none"; + cases: TestCase[]; +}[] = [ + { + html_handling: "auto-trailing-slash", + cases: [ + { + title: "/[boop] -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/[boop]", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D -> 200 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/%5Bboop%5D", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + // auto-trailing-slash html handling still works + { + title: "/%5Bboop%5D.html -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/%5Bboop%5D.html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/[boop].html -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/[boop].html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D/ -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/%5Bboop%5D/", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/[boop]/ -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/[boop]/", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/[boop] -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/[boop]", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D -> 200 (with /[boop].html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/%5Bboop%5D", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/[boop].html -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/[boop].html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D.html -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/%5Bboop%5D.html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/[boop]/ -> /%5Bboop%5D/ 307 (with /[boop]/index.html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/[boop]/", + matchedFile: "/[boop]/index.html", + finalPath: "/%5Bboop%5D/", + }, + { + title: "/%5Bboop%5D/ -> 200 (with /[boop]/index.html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/%5Bboop%5D/", + matchedFile: "/[boop]/index.html", + finalPath: "/%5Bboop%5D/", + }, + { + title: + "/[boop]/index.html -> /%5Bboop%5D/ 307 (with /[boop]/index.html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/[boop]/index.html", + matchedFile: "/[boop]/index.html", + finalPath: "/%5Bboop%5D/", + }, + { + title: + "/%5Bboop%5D/index.html -> /%5Bboop%5D/ 307 (with /[boop]/index.html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/%5Bboop%5D/index.html", + matchedFile: "/[boop]/index.html", + finalPath: "/%5Bboop%5D/", + }, + // paths with a mix of encoded and unencoded characters + { + title: + "/beep/[b%C3%B2op] -> /beep/%5Bb%C3%B2op%5D 307 (with /beep/[bòop].html)", + files: ["/beep/[bòop].html"], + requestPath: "/beep/[b%C3%B2op]", + matchedFile: "/beep/[bòop].html", + finalPath: "/beep/%5Bb%C3%B2op%5D", + }, + // user-encoded paths should only be accessible at the (double) encoded path + { + title: "/[boop] -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/[boop]", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/[boop].html -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/[boop].html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D -> 200 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%5Bboop%5D", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D.html -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%5Bboop%5D.html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D -> 200 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%5Bboop%5D", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%255Bboop%255D -> 200 (with /%5Bboop%5D.html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%255Bboop%255D", + matchedFile: "/%5Bboop%5D.html", + finalPath: "/%255Bboop%255D", + }, + { + title: + "/%255Bboop%255D.html -> /%255Bboop%255D 307 (with /%5Bboop%5D.html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%255Bboop%255D.html", + matchedFile: "/%5Bboop%5D.html", + finalPath: "/%255Bboop%255D", + }, + { + title: "/beep?boop -> 404", + files: ["/beep?boop.html"], + requestPath: "/beep?boop", + }, + { + title: "/beep%3Fboop -> 200 (with /beep?boop.html)", + files: ["/beep?boop.html"], + requestPath: "/beep%3Fboop", + matchedFile: "/beep?boop.html", + finalPath: "/beep%3Fboop", + }, + { + title: "/beep%3Fboop/ -> /beep%3Fboop 307 (with /beep?boop.html)", + files: ["/beep?boop.html"], + requestPath: "/beep%3Fboop/", + matchedFile: "/beep?boop.html", + finalPath: "/beep%3Fboop", + }, + ], + }, + { + html_handling: "drop-trailing-slash", + cases: [ + { + title: "/[boop] -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/[boop]", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D -> 200 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/%5Bboop%5D", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + // drop-trailing-slash html handling still works + { + title: "/%5Bboop%5D.html -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/%5Bboop%5D.html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/[boop].html -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/[boop].html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D/ -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/%5Bboop%5D/", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/[boop]/ -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/[boop]/", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/[boop] -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/[boop]", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D -> 200 (with /[boop].html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/%5Bboop%5D", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/[boop].html -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/[boop].html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D.html -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/%5Bboop%5D.html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/[boop]/ -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/[boop]/", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D/ -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/%5Bboop%5D/", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: + "/[boop]/index.html -> /%5Bboop%5D/index.html 307 (with /[boop]/index.html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/[boop]/index.html", + matchedFile: "/[boop]/index.html", + finalPath: "/%5Bboop%5D/index.html", + }, + { + title: "/%5Bboop%5D/index.html -> 200 (with /[boop]/index.html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/%5Bboop%5D/index.html", + matchedFile: "/[boop]/index.html", + finalPath: "/%5Bboop%5D/index.html", + }, + // paths with a mix of encoded and unencoded characters + { + title: + "/beep/[b%C3%B2op] -> /beep/%5Bb%C3%B2op%5D 307 (with /beep/[bòop].html)", + files: ["/beep/[bòop].html"], + requestPath: "/beep/[b%C3%B2op]", + matchedFile: "/beep/[bòop].html", + finalPath: "/beep/%5Bb%C3%B2op%5D", + }, + // user-encoded paths should only be accessible at the (double) encoded path + { + title: "/[boop] -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/[boop]", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/[boop].html -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/[boop].html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D -> 200 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%5Bboop%5D", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D.html -> /%5Bboop%5D 307 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%5Bboop%5D.html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%5Bboop%5D -> 200 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%5Bboop%5D", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D", + }, + { + title: "/%255Bboop%255D -> 200 (with /%5Bboop%5D.html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%255Bboop%255D", + matchedFile: "/%5Bboop%5D.html", + finalPath: "/%255Bboop%255D", + }, + { + title: + "/%255Bboop%255D.html -> /%255Bboop%255D 307 (with /%5Bboop%5D.html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%255Bboop%255D.html", + matchedFile: "/%5Bboop%5D.html", + finalPath: "/%255Bboop%255D", + }, + { + title: "/beep?boop -> 404", + files: ["/beep?boop.html"], + requestPath: "/beep?boop", + }, + { + title: "/beep%3Fboop -> 200 (with /beep?boop.html)", + files: ["/beep?boop.html"], + requestPath: "/beep%3Fboop", + matchedFile: "/beep?boop.html", + finalPath: "/beep%3Fboop", + }, + { + title: "/beep%3Fboop/ -> /beep%3Fboop 307 (with /beep?boop.html)", + files: ["/beep?boop.html"], + requestPath: "/beep%3Fboop/", + matchedFile: "/beep?boop.html", + finalPath: "/beep%3Fboop", + }, + ], + }, + { + html_handling: "force-trailing-slash", + cases: [ + { + title: "/%5Bboop%5D/ -> 200 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/%5Bboop%5D/", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D/", + }, + { + title: "/[boop]/ -> /%5Bboop%5D/ 307 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/[boop]/", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D/", + }, + // force-trailing-slash html handling still works + { + title: "/[boop] -> /%5Bboop%5D/ 307 (with /[boop]/index.html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/[boop]", + matchedFile: "/[boop]/index.html", + finalPath: "/%5Bboop%5D/", + }, + { + title: "/%5Bboop%5D -> /%5Bboop%5D/ 307 (with /[boop]/index.html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/%5Bboop%5D", + matchedFile: "/[boop]/index.html", + finalPath: "/%5Bboop%5D/", + }, + { + title: "/[boop].html -> /%5Bboop%5D.html 307 (with /[boop].html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/[boop].html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D.html", + }, + { + title: "/%5Bboop%5D.html -> 200 (with /[boop].html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/%5Bboop%5D.html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D.html", + }, + { + title: "/[boop]/ -> /%5Bboop%5D/ 307 (with /[boop]/index.html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/[boop]/", + matchedFile: "/[boop]/index.html", + finalPath: "/%5Bboop%5D/", + }, + { + title: "/%5Bboop%5D/ -> 200 (with /[boop]/index.html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/%5Bboop%5D/", + matchedFile: "/[boop]/index.html", + finalPath: "/%5Bboop%5D/", + }, + { + title: + "/[boop]/index.html -> /%5Bboop%5D/ 307 (with /[boop]/index.html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/[boop]/index.html", + matchedFile: "/[boop]/index.html", + finalPath: "/%5Bboop%5D/", + }, + { + title: + "/%5Bboop%5D/index.html -> /%5Bboop%5D/ 307 (with /[boop]/index.html)", + files: ["/[boop].html", "/[boop]/index.html"], + requestPath: "/%5Bboop%5D/index.html", + matchedFile: "/[boop]/index.html", + finalPath: "/%5Bboop%5D/", + }, + // paths with a mix of encoded and unencoded characters + { + title: + "/beep/[b%C3%B2op]/ -> /beep/%5Bb%C3%B2op%5D/ 307 (with /beep/[bòop].html)", + files: ["/beep/[bòop].html"], + requestPath: "/beep/[b%C3%B2op]/", + matchedFile: "/beep/[bòop].html", + finalPath: "/beep/%5Bb%C3%B2op%5D/", + }, + // user-encoded paths should only be accessible at the (double) encoded path + { + title: "/[boop] -> /%5Bboop%5D/ 307 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/[boop]", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D/", + }, + { + title: "/[boop].html -> /%5Bboop%5D/ 307 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/[boop].html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D/", + }, + { + title: "/%5Bboop%5D -> /%5Bboop%5D/ 307 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%5Bboop%5D", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D/", + }, + { + title: "/%5Bboop%5D.html -> /%5Bboop%5D/ 307 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%5Bboop%5D.html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D/", + }, + { + title: "/%5Bboop%5D -> /%5Bboop%5D/ 307 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%5Bboop%5D", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D/", + }, + { + title: + "/%255Bboop%255D -> /%255Bboop%255D/ 307 (with /%5Bboop%5D.html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%255Bboop%255D", + matchedFile: "/%5Bboop%5D.html", + finalPath: "/%255Bboop%255D/", + }, + { + title: + "/%255Bboop%255D.html -> /%255Bboop%255D/ 307 (with /%5Bboop%5D.html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%255Bboop%255D.html", + matchedFile: "/%5Bboop%5D.html", + finalPath: "/%255Bboop%255D/", + }, + { + title: "/beep?boop/ -> 404", + files: ["/beep?boop.html"], + requestPath: "/beep?boop/", + }, + { + title: "/beep%3Fboop -> /beep%3Fboop/ 307 (with /beep?boop.html)", + files: ["/beep?boop.html"], + requestPath: "/beep%3Fboop", + matchedFile: "/beep?boop.html", + finalPath: "/beep%3Fboop/", + }, + { + title: "/beep%3Fboop/ -> 200 (with /beep?boop.html)", + files: ["/beep?boop.html"], + requestPath: "/beep%3Fboop/", + matchedFile: "/beep?boop.html", + finalPath: "/beep%3Fboop/", + }, + ], + }, + { + html_handling: "none", + cases: [ + { + title: "/[boop] -> 404", + files: ["/[boop].html"], + requestPath: "/[boop]", + }, + { + title: "/%5Bboop%5D -> 404", + files: ["/[boop].html"], + requestPath: "/%5Bboop%5D", + }, + // encoding still operates when html_handling is set to 'none' + { + title: "/[boop].html -> /%5Bboop%5D.html 307 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/[boop].html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D.html", + }, + { + title: "/%5Bboop%5D.html -> 200 (with /[boop].html)", + files: ["/[boop].html"], + requestPath: "/%5Bboop%5D.html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D.html", + }, + // mix of encoded and unencoded paths + { + title: + "/beep/[b%C3%B2op].html -> /beep/%5Bb%C3%B2op%5D.html 307 (with /beep/[bòop].html)", + files: ["/beep/[bòop].html"], + requestPath: "/beep/[b%C3%B2op].html", + matchedFile: "/beep/[bòop].html", + finalPath: "/beep/%5Bb%C3%B2op%5D.html", + }, + // user-encoded paths should only be accessible at the (double) encoded path + { + title: "/[boop].html -> /%5Bboop%5D.html 307 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/[boop].html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D.html", + }, + { + title: "/%5Bboop%5D.html -> 200 (with /[boop].html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%5Bboop%5D.html", + matchedFile: "/[boop].html", + finalPath: "/%5Bboop%5D.html", + }, + { + title: "/[boop] -> 404", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/[boop]", + }, + { + title: "/%5Bboop%5D -> 404", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%5Bboop%5D", + }, + { + title: "/%255Bboop%255D.html -> 200 (with /%5Bboop%5D.html)", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%255Bboop%255D.html", + matchedFile: "/%5Bboop%5D.html", + finalPath: "/%255Bboop%255D.html", + }, + { + title: "/%255Bboop%255D -> 404", + files: ["/%5Bboop%5D.html", "/[boop].html"], + requestPath: "/%255Bboop%255D", + }, + { + title: "/beep?boop/ -> 404", + files: ["/beep?boop.html"], + requestPath: "/beep?boop/", + }, + { + title: "/beep%3Fboop.html -> 200 (with /beep?boop.html)", + files: ["/beep?boop.html"], + requestPath: "/beep%3Fboop.html", + matchedFile: "/beep?boop.html", + finalPath: "/beep%3Fboop.html", + }, + { + title: "/beep%3Fboop -> 404", + files: ["/beep?boop.html"], + requestPath: "/beep%3Fboop", + }, + ], + }, +]; diff --git a/fixtures/asset-config/test-cases/html-handling-test-cases.ts b/fixtures/asset-config/test-cases/html-handling-test-cases.ts new file mode 100644 index 000000000000..8c65ebac26aa --- /dev/null +++ b/fixtures/asset-config/test-cases/html-handling-test-cases.ts @@ -0,0 +1,788 @@ +import { TestCase } from "../html-handling.test"; + +export const htmlHandlingTestCases: { + html_handling: + | "auto-trailing-slash" + | "drop-trailing-slash" + | "force-trailing-slash" + | "none"; + cases: TestCase[]; +}[] = [ + { + html_handling: "auto-trailing-slash", + cases: [ + { + title: "/ -> 200 (with /index.html)", + files: ["/index.html"], + requestPath: "/index.html", + matchedFile: "/index.html", + finalPath: "/", + }, + { + title: "/index -> / 307 (with /index.html)", + files: ["/index.html"], + requestPath: "/index", + matchedFile: "/index.html", + finalPath: "/", + }, + { + title: "/index.html -> / 307 (with /index.html)", + files: ["/index.html"], + requestPath: "/index.html", + matchedFile: "/index.html", + finalPath: "/", + }, + { + title: "/both -> 200 (with /both.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both", + matchedFile: "/both.html", + finalPath: "/both", + }, + { + title: "/both.html -> /both 307 (with /both.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both.html", + matchedFile: "/both.html", + finalPath: "/both", + }, + { + title: "/both/ -> 200 (with /both/index.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both/", + matchedFile: "/both/index.html", + finalPath: "/both/", + }, + { + title: "/both/index.html -> /both/ 307 (with /both/index.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both/index.html", + matchedFile: "/both/index.html", + finalPath: "/both/", + }, + { + title: "/both/index -> /both/ 307 (with /both/index.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both/index", + matchedFile: "/both/index.html", + finalPath: "/both/", + }, + { + title: "/file -> 200 (with file.html)", + files: ["/file.html"], + requestPath: "/file", + matchedFile: "/file.html", + finalPath: "/file", + }, + { + title: "/file.html -> /file 307 (with file.html)", + files: ["/file.html"], + requestPath: "/file.html", + matchedFile: "/file.html", + finalPath: "/file", + }, + { + title: "/file/ -> /file 307 (with file.html)", + files: ["/file.html"], + requestPath: "/file/", + matchedFile: "/file.html", + finalPath: "/file", + }, + { + title: "/file/index -> /file 307 (with file.html)", + files: ["/file.html"], + requestPath: "/file/index", + matchedFile: "/file.html", + finalPath: "/file", + }, + { + title: "/file/index.html -> /file 307 (with file.html)", + files: ["/file.html"], + requestPath: "/file/index.html", + matchedFile: "/file.html", + finalPath: "/file", + }, + { + title: "/folder -> /folder/ 307 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder", + matchedFile: "/folder/index.html", + finalPath: "/folder/", + }, + { + title: "/folder.html -> /folder/ 307 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder.html", + matchedFile: "/folder/index.html", + finalPath: "/folder/", + }, + { + title: "/folder/ -> 200 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder/", + matchedFile: "/folder/index.html", + finalPath: "/folder/", + }, + { + title: "/folder/index -> /folder/ 307 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder/index", + matchedFile: "/folder/index.html", + finalPath: "/folder/", + }, + { + title: "/folder/index.html -> /folder/ 307 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder/index.html", + matchedFile: "/folder/index.html", + finalPath: "/folder/", + }, + // see encoding tests, but tldr only accessible at the (double) encoded path + { + title: "/bin -> /bin/ 307 (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + { + title: "/bin.html -> /bin/ 307 (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin.html", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + // This is a bit rogue, but then so is the test case + { + title: "/bin%2F -> /bin 307 (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin%2F", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + { + title: "/bin%252F -> 200 (with /bin%2F)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin%252F", + matchedFile: "/bin%2F", + finalPath: "/bin%252F", + }, + { + title: "/bin/ -> 200 (with /bin/index.html not /bin%2F", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin/", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + { + title: "/bin/index -> 307 /bin/ (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin/index", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + { + title: "/bin/index.html -> 307 /bin/ (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin/index.html", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + // prefers exact match + { + title: "/file-bin -> 200 ", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin", + matchedFile: "/file-bin", + finalPath: "/file-bin", + }, + // (doesn't rewrite if resulting path would match another asset) + { + title: "/file-bin.html -> 200 ", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin.html", + matchedFile: "/file-bin.html", + finalPath: "/file-bin.html", + }, + // (finds file-bin.html --rewrite--> /file-bin, but /file-bin exists) + { + title: "/file-bin/ -> 404 ", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin/", + }, + { + title: "/file-bin/index -> 404 ", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin/index", + }, + { + title: "/file-bin/index.html -> 404 ", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin/index.html", + }, + ], + }, + { + html_handling: "drop-trailing-slash", + cases: [ + // note that we don't drop the "/" if that is the only path component + { + title: "/ -> 200 (with /index.html)", + files: ["/index.html"], + requestPath: "/index.html", + matchedFile: "/index.html", + finalPath: "/", + }, + { + title: "/index -> / 307 (with /index.html)", + files: ["/index.html"], + requestPath: "/index", + matchedFile: "/index.html", + finalPath: "/", + }, + { + title: "/index.html -> / 307 (with /index.html)", + files: ["/index.html"], + requestPath: "/index.html", + matchedFile: "/index.html", + finalPath: "/", + }, + { + title: "/both -> 200 (with /both.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both", + matchedFile: "/both.html", + finalPath: "/both", + }, + { + title: "/both.html -> /both 307 (with /both.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both.html", + matchedFile: "/both.html", + finalPath: "/both", + }, + // drops trailing slash and so it tries /both.html first + { + title: "/both/ -> /both 307 (with /both.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both/", + matchedFile: "/both.html", + finalPath: "/both", + }, + { + title: "/both/index -> 307 (with /both.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both/index", + matchedFile: "/both.html", + finalPath: "/both", + }, + // can't rewrite /both/index.html: would be /both/ -> /both -> /both.html + // ie can only access /both/index.html by exact match + { + title: "/both/index.html -> 200 (with /both/index.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both/index.html", + matchedFile: "/both/index.html", + finalPath: "/both/index.html", + }, + { + title: "/file -> 200 (with file.html)", + files: ["/file.html"], + requestPath: "/file", + matchedFile: "/file.html", + finalPath: "/file", + }, + { + title: "/file.html -> /file 307 (with file.html)", + files: ["/file.html"], + requestPath: "/file.html", + matchedFile: "/file.html", + finalPath: "/file", + }, + { + title: "/file/ -> /file 307 (with file.html)", + files: ["/file.html"], + requestPath: "/file/", + matchedFile: "/file.html", + finalPath: "/file", + }, + { + title: "/file/index -> /file 307 (with file.html)", + files: ["/file.html"], + requestPath: "/file/index", + matchedFile: "/file.html", + finalPath: "/file", + }, + { + title: "/file/index.html -> /file 307 (with file.html)", + files: ["/file.html"], + requestPath: "/file/index.html", + matchedFile: "/file.html", + finalPath: "/file", + }, + { + title: "/folder -> 200 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder", + matchedFile: "/folder/index.html", + finalPath: "/folder", + }, + { + title: "/folder.html -> /folder 307 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder.html", + matchedFile: "/folder/index.html", + finalPath: "/folder", + }, + { + title: "/folder/ -> /folder 307 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder/", + matchedFile: "/folder/index.html", + finalPath: "/folder", + }, + { + title: "/folder/index -> /folder 307 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder/index", + matchedFile: "/folder/index.html", + finalPath: "/folder", + }, + { + title: "/folder/index.html -> /folder 307 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder/index.html", + matchedFile: "/folder/index.html", + finalPath: "/folder", + }, + { + title: "/bin -> 200 (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin", + matchedFile: "/bin/index.html", + finalPath: "/bin", + }, + { + title: "/bin.html -> /bin 307 (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin.html", + matchedFile: "/bin/index.html", + finalPath: "/bin", + }, + // This is a bit rogue, but then so is the test case + { + title: "/bin%2F -> /bin 307 (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin%2F", + matchedFile: "/bin/index.html", + finalPath: "/bin", + }, + { + title: "/bin%252F -> 200 (with /bin%2F)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin%252F", + matchedFile: "/bin%2F", + finalPath: "/bin%252F", + }, + { + title: "/bin/ -> /bin 307 (with /bin/index.html not /bin%2F", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin/", + matchedFile: "/bin/index.html", + finalPath: "/bin", + }, + { + title: "/bin/index -> /bin 307 (with /bin/index.html not /bin%2F", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin/index", + matchedFile: "/bin/index.html", + finalPath: "/bin", + }, + { + title: "/bin/index.html -> /bin 307 (with /bin/index.html not /bin%2F", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin/index.html", + matchedFile: "/bin/index.html", + finalPath: "/bin", + }, + { + title: "/file-bin -> 200", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin", + matchedFile: "/file-bin", + finalPath: "/file-bin", + }, + // doesn't redirect to /file-bin because that also exists + { + title: "/file-bin.html -> 200 (with /file-bin.html)", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin.html", + matchedFile: "/file-bin.html", + finalPath: "/file-bin.html", + }, + // 404s because ambiguity between /file-bin or /file-bin.html? + { + title: "/file-bin/ -> 404", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin/", + }, + { + title: "/file-bin/index -> 404", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin/index", + }, + { + title: "/file-bin/index.html -> 404", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin/index.html", + }, + ], + }, + { + html_handling: "force-trailing-slash", + cases: [ + { + title: "/ -> 200 (with /index.html)", + files: ["/index.html"], + requestPath: "/index.html", + matchedFile: "/index.html", + finalPath: "/", + }, + { + title: "/index -> / 307 (with /index.html)", + files: ["/index.html"], + requestPath: "/index", + matchedFile: "/index.html", + finalPath: "/", + }, + { + title: "/index.html -> / 307 (with /index.html)", + files: ["/index.html"], + requestPath: "/index.html", + matchedFile: "/index.html", + finalPath: "/", + }, + // ie tries /both/index.html first + { + title: "/both -> /both/ 307 (with /both/index.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both", + matchedFile: "/both/index.html", + finalPath: "/both/", + }, + // can't rewrite /both.html: would be /both -> /both/ -> /both/index.html + // ie can only access /both.html by exact match + { + title: "/both.html -> 200", + files: ["/both.html", "/both/index.html"], + requestPath: "/both.html", + matchedFile: "/both.html", + finalPath: "/both.html", + }, + { + title: "/both/ -> 200 (with /both/index.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both/", + matchedFile: "/both/index.html", + finalPath: "/both/", + }, + { + title: "/both/index -> /both/ 307 (with /both/index.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both/index", + matchedFile: "/both/index.html", + finalPath: "/both/", + }, + { + title: "/both/index.html -> /both/ 307 (with /both/index.html)", + files: ["/both.html", "/both/index.html"], + requestPath: "/both/index.html", + matchedFile: "/both/index.html", + finalPath: "/both/", + }, + // always ends in a trailing slash + { + title: "/file -> /file/ 307 (with file.html)", + files: ["/file.html"], + requestPath: "/file", + matchedFile: "/file.html", + finalPath: "/file/", + }, + { + title: "/file.html -> /file/ 307 (with file.html)", + files: ["/file.html"], + requestPath: "/file.html", + matchedFile: "/file.html", + finalPath: "/file/", + }, + + { + title: "/file/ -> 200 (with file.html)", + files: ["/file.html"], + requestPath: "/file/", + matchedFile: "/file.html", + finalPath: "/file/", + }, + { + title: "/file/index -> /file/ 307 (with file.html)", + files: ["/file.html"], + requestPath: "/file/index", + matchedFile: "/file.html", + finalPath: "/file/", + }, + { + title: "/file/index.html -> /file/ 307 (with file.html)", + files: ["/file.html"], + requestPath: "/file/index.html", + matchedFile: "/file.html", + finalPath: "/file/", + }, + { + title: "/folder -> /folder/ 307 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder", + matchedFile: "/folder/index.html", + finalPath: "/folder/", + }, + { + title: "/folder.html -> /folder/ 307 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder.html", + matchedFile: "/folder/index.html", + finalPath: "/folder/", + }, + { + title: "/folder/ -> 200 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder/", + matchedFile: "/folder/index.html", + finalPath: "/folder/", + }, + { + title: "/folder/index -> /folder/ 307 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder/index", + matchedFile: "/folder/index.html", + finalPath: "/folder/", + }, + { + title: "/folder/index.html -> /folder/ 307 (with /folder/index.html)", + files: ["/folder/index.html"], + requestPath: "/folder/index.html", + matchedFile: "/folder/index.html", + finalPath: "/folder/", + }, + { + title: "/bin -> /bin/ 307 (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + { + title: "/bin.html -> /bin/ 307 (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin.html", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + { + title: "/bin%2F -> /bin/ 307 (with /bin%2F)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin%2F", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + // This is a bit rogue, but then so is the test case + { + title: "/bin%2F -> /bin/ 307 (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin%2F", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + { + title: "/bin%252F -> 200 (with /bin%2F)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin%252F", + matchedFile: "/bin%2F", + finalPath: "/bin%252F", + }, + { + title: "/bin/ -> 200 (with /bin/index.html not /bin%2F", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin/", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + { + title: "/bin/index -> /bin/ 307 (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin/index", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + { + title: "/bin/index.html -> /bin/ 307 (with /bin/index.html)", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin/index.html", + matchedFile: "/bin/index.html", + finalPath: "/bin/", + }, + // doesn't force a trailing slash here because it would redirect to /file-bin.html + { + title: "/file-bin -> 200", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin", + matchedFile: "/file-bin", + finalPath: "/file-bin", + }, + { + title: "/file-bin.html -> /file-bin/ 307 (with /file-bin.html)", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin.html", + matchedFile: "/file-bin.html", + finalPath: "/file-bin/", + }, + { + title: "/file-bin/ -> 200", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin/", + matchedFile: "/file-bin.html", + finalPath: "/file-bin/", + }, + { + title: "/file-bin/index -> /file-bin/ 307 (with /file-bin.html)", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin/index", + matchedFile: "/file-bin.html", + finalPath: "/file-bin/", + }, + { + title: "/file-bin/index.html -> /file-bin/ 307 (with /file-bin.html)", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin/index.html", + matchedFile: "/file-bin.html", + finalPath: "/file-bin/", + }, + ], + }, + { + html_handling: "none", + cases: [ + { + title: "/ -> 404", + files: ["/index.html"], + requestPath: "/", + }, + { + title: "/index -> 404", + files: ["/index.html"], + requestPath: "/index", + }, + { + title: "/index.html -> 200", + files: ["/index.html"], + requestPath: "/index.html", + matchedFile: "/index.html", + finalPath: "/index.html", + }, + { + title: "/both -> 404", + files: ["/both.html", "/both/index.html"], + requestPath: "/both", + }, + { + title: "/both.html -> 200", + files: ["/both.html", "/both/index.html"], + requestPath: "/both.html", + matchedFile: "/both.html", + finalPath: "/both.html", + }, + { + title: "/both/ -> 404", + files: ["/both.html", "/both/index.html"], + requestPath: "/both/", + }, + { + title: "/both/index.html -> 200", + files: ["/both.html", "/both/index.html"], + requestPath: "/both/index.html", + matchedFile: "/both/index.html", + finalPath: "/both/index.html", + }, + { + title: "/file/index.html -> 404", + files: ["/file.html"], + requestPath: "/file/index.html", + }, + { + title: "/folder.html -> 404", + files: ["/folder/index.html"], + requestPath: "/folder.html", + }, + { + title: "/bin -> 404", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin", + }, + { + title: "/bin.html -> 404", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin.html", + }, + // encoding is independent of html handling + { + title: "/bin%2F -> 404", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin%2F", // -> /bin/ -> 404 + }, + { + title: "/bin%252F -> 200", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin%252F", + matchedFile: "/bin%2F", + finalPath: "/bin%252F", + }, + { + title: "/bin/ -> 404", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin/", + }, + { + title: "/bin/index -> 404", + files: ["/bin%2F", "/bin/index.html"], + requestPath: "/bin/index", + }, + { + title: "/file-bin -> 200", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin", + matchedFile: "/file-bin", + finalPath: "/file-bin", + }, + { + title: "/file-bin.html -> 200", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin.html", + matchedFile: "/file-bin.html", + finalPath: "/file-bin.html", + }, + { + title: "/file-bin/ -> 404", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin/", + }, + { + title: "/file-bin/index -> 404", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin/index", + }, + { + title: "/file-bin/index.html -> 404", + files: ["/file-bin", "/file-bin.html"], + requestPath: "/file-bin/index.html", + }, + ], + }, +];