File
Blob: src/worker/webdav/propfind.ts
| 1 | import { davError, davResponse, parseDepth } from "@/worker/dav/http"; |
| 2 | import { maxDavDepthInfinityNodes, maxXmlBodyBytes } from "@/worker/dav/limits"; |
| 3 | import { parsePropfindXml, type PropfindRequest } from "@/worker/xml/dav-request"; |
| 4 | import type { AppContext } from "@/worker/types"; |
| 5 | import type { SubjectRow } from "@/worker/db/d1/schema"; |
| 6 | import { fileDavObject, resultError, type NormalizedFilesRequestPath } from "@/worker/webdav/object"; |
| 7 | import { multistatusXml, nodePropstats } from "@/worker/webdav/props"; |
| 8 | |
| 9 | export async function handlePropfind(c: AppContext, subject: SubjectRow, requestPath: NormalizedFilesRequestPath) { |
| 10 | const depth = parseDepth(c.req.header("depth") ?? null, "infinity"); |
| 11 | if (!depth) return davError(400, "Invalid Depth header"); |
| 12 | let parsed: PropfindRequest; |
| 13 | try { |
| 14 | parsed = parsePropfindXml(await c.req.text(), maxXmlBodyBytes(c.env)); |
| 15 | } catch (cause) { |
| 16 | return davError(400, cause instanceof Error ? cause.message : "Invalid PROPFIND body"); |
| 17 | } |
| 18 | const result = await fileDavObject(c.env, subject.storageId).propfind({ |
| 19 | subjectId: subject.id, |
| 20 | storageId: subject.storageId, |
| 21 | path: requestPath.path, |
| 22 | depth, |
| 23 | maxNodes: maxDavDepthInfinityNodes(c.env), |
| 24 | nowMs: Date.now(), |
| 25 | }); |
| 26 | if (!result.ok) return resultError(result); |
| 27 | return davResponse( |
| 28 | multistatusXml(result.nodes.map((node) => ({ href: node.href, propstats: nodePropstats(node, parsed) }))), |
| 29 | 207, |
| 30 | ); |
| 31 | } |