Skip to content
File

Blob: src/worker/webdav/copy-move.ts

typescript54 lines
1import { parseDestination, overwriteAllowed } from "@/worker/dav/destination";
2import { davError, emptyResponse } from "@/worker/dav/http";
3import { maxDavDepthInfinityNodes } from "@/worker/dav/limits";
4import type { SubjectRow } from "@/worker/db/d1/schema";
5import type { AppContext } from "@/worker/types";
6import { enqueueGc } from "@/worker/webdav/gc";
7import { fileDavObject, resultError, type NormalizedFilesRequestPath } from "@/worker/webdav/object";
8import { readCopyDepth, readFileDavWriteRequest, validateMoveDepth } from "@/worker/webdav/request";
9 
10export async function handleCopyMove(c: AppContext, subject: SubjectRow, path: NormalizedFilesRequestPath) {
11 const destination = parseDestination(c.req.header("destination") ?? null, new URL(c.req.url));
12 if (!destination.ok) return davError(destination.status, destination.message);
13 const overwrite = overwriteAllowed(c.req.header("overwrite") ?? null);
14 if (overwrite === null) return davError(400, "Invalid Overwrite header");
15 const writeRequest = readFileDavWriteRequest(c.req.raw);
16 if (writeRequest instanceof Response) return writeRequest;
17 const rawDepth = c.req.header("depth") ?? null;
18 let copyDepth: "0" | "infinity" = "infinity";
19 if (c.req.method === "COPY") {
20 const depth = readCopyDepth(rawDepth);
21 if (depth instanceof Response) return depth;
22 copyDepth = depth;
23 } else {
24 const depthError = validateMoveDepth(rawDepth);
25 if (depthError) return depthError;
26 }
27 const object = fileDavObject(c.env, subject.storageId);
28 const maxNodes = maxDavDepthInfinityNodes(c.env);
29 const result =
30 c.req.method === "COPY"
31 ? await object.copy({
32 subjectId: subject.id,
33 storageId: subject.storageId,
34 from: path.path,
35 to: destination.path,
36 depth: copyDepth,
37 overwrite,
38 ...writeRequest,
39 maxNodes,
40 })
41 : await object.move({
42 subjectId: subject.id,
43 storageId: subject.storageId,
44 from: path.path,
45 to: destination.path,
46 overwrite,
47 ...writeRequest,
48 maxNodes,
49 });
50 if (!result.ok) return resultError(result);
51 await enqueueGc(c, subject, result.blobGc);
52 return emptyResponse(result.created ? 201 : 204);
53}