File
Blob: tests/worker/protocol/webdav/files-limits.workers.test.ts
| 1 | import { describe, expect, it } from "vitest"; |
| 2 | |
| 3 | import { createDavFixture, davRequest } from "@tests/worker/helpers/dav"; |
| 4 | import { fetchWorker } from "@tests/worker/helpers/http"; |
| 5 | import { withEnvBinding } from "@tests/worker/helpers/env"; |
| 6 | import { name } from "./files-helpers"; |
| 7 | |
| 8 | describe("WebDAV file limits", () => { |
| 9 | it("rejects over-limit XML request bodies", async () => { |
| 10 | const fixture = await createDavFixture(); |
| 11 | const body = `<?xml version="1.0"?><D:propfind xmlns:D="DAV:"><D:prop><D:displayname>${"x".repeat( |
| 12 | 1_049_000, |
| 13 | )}</D:displayname></D:prop></D:propfind>`; |
| 14 | const response = await fetchWorker( |
| 15 | davRequest(fixture, "/files/", { |
| 16 | method: "PROPFIND", |
| 17 | headers: { depth: "0", "content-type": "application/xml" }, |
| 18 | body, |
| 19 | }), |
| 20 | ); |
| 21 | |
| 22 | expect(response.status).toBe(400); |
| 23 | await expect(response.text()).resolves.toContain("XML body exceeds"); |
| 24 | }); |
| 25 | |
| 26 | it("bounds Depth infinity PROPFIND by the configured maximum nodes", async () => { |
| 27 | const fixture = await createDavFixture(); |
| 28 | const directory = name("depth-bound"); |
| 29 | expect(await fetchWorker(davRequest(fixture, `/files/${directory}/`, { method: "MKCOL" }))).toMatchObject({ |
| 30 | status: 201, |
| 31 | }); |
| 32 | expect( |
| 33 | await fetchWorker(davRequest(fixture, `/files/${directory}/a.txt`, { method: "PUT", body: "a" })), |
| 34 | ).toHaveProperty("status", 201); |
| 35 | expect( |
| 36 | await fetchWorker(davRequest(fixture, `/files/${directory}/b.txt`, { method: "PUT", body: "b" })), |
| 37 | ).toHaveProperty("status", 201); |
| 38 | |
| 39 | await withEnvBinding("MAX_DAV_DEPTH_INFINITY_NODES", "2", async () => { |
| 40 | const response = await fetchWorker( |
| 41 | davRequest(fixture, "/files/", { |
| 42 | method: "PROPFIND", |
| 43 | headers: { depth: "infinity", "content-type": "application/xml" }, |
| 44 | body: `<?xml version="1.0"?><D:propfind xmlns:D="DAV:"><D:prop><D:displayname/></D:prop></D:propfind>`, |
| 45 | }), |
| 46 | ); |
| 47 | expect(response.status).toBe(403); |
| 48 | await expect(response.text()).resolves.toContain("configured maximum"); |
| 49 | }); |
| 50 | }); |
| 51 | |
| 52 | it("fails recursive DELETE, COPY, and MOVE before mutation when the subtree exceeds the configured node limit", async () => { |
| 53 | const fixture = await createDavFixture(); |
| 54 | const directory = name("recursive-bound"); |
| 55 | expect(await fetchWorker(davRequest(fixture, `/files/${directory}/`, { method: "MKCOL" }))).toHaveProperty( |
| 56 | "status", |
| 57 | 201, |
| 58 | ); |
| 59 | expect( |
| 60 | await fetchWorker(davRequest(fixture, `/files/${directory}/a.txt`, { method: "PUT", body: "a" })), |
| 61 | ).toHaveProperty("status", 201); |
| 62 | expect( |
| 63 | await fetchWorker(davRequest(fixture, `/files/${directory}/b.txt`, { method: "PUT", body: "b" })), |
| 64 | ).toHaveProperty("status", 201); |
| 65 | |
| 66 | await withEnvBinding("MAX_DAV_DEPTH_INFINITY_NODES", "2", async () => { |
| 67 | const deleted = await fetchWorker(davRequest(fixture, `/files/${directory}/`, { method: "DELETE" })); |
| 68 | expect(deleted.status).toBe(403); |
| 69 | expect(await fetchWorker(davRequest(fixture, `/files/${directory}/a.txt`))).toHaveProperty("status", 200); |
| 70 | |
| 71 | const copied = await fetchWorker( |
| 72 | davRequest(fixture, `/files/${directory}/`, { |
| 73 | method: "COPY", |
| 74 | headers: { destination: `https://${fixture.hostLabel}.dav.example.com/files/${directory}-copy/` }, |
| 75 | }), |
| 76 | ); |
| 77 | expect(copied.status).toBe(403); |
| 78 | expect(await fetchWorker(davRequest(fixture, `/files/${directory}-copy/a.txt`))).toHaveProperty("status", 404); |
| 79 | |
| 80 | const moved = await fetchWorker( |
| 81 | davRequest(fixture, `/files/${directory}/`, { |
| 82 | method: "MOVE", |
| 83 | headers: { destination: `https://${fixture.hostLabel}.dav.example.com/files/${directory}-moved/` }, |
| 84 | }), |
| 85 | ); |
| 86 | expect(moved.status).toBe(403); |
| 87 | expect(await fetchWorker(davRequest(fixture, `/files/${directory}/a.txt`))).toHaveProperty("status", 200); |
| 88 | expect(await fetchWorker(davRequest(fixture, `/files/${directory}-moved/a.txt`))).toHaveProperty("status", 404); |
| 89 | }); |
| 90 | }); |
| 91 | }); |