Skip to content

Commit

Permalink
add1
Browse files Browse the repository at this point in the history
  • Loading branch information
aigem committed Sep 11, 2024
1 parent 7562b18 commit 2c03f37
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 34 deletions.
50 changes: 25 additions & 25 deletions src/handlers/webdavHandler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { listAll, fromR2Object, make_resource_pathfindResponse, generateMultiStatus } from '../utils/webdavUtils';
import { listAll, fromR2Object, make_resource_path, generatePropfindResponse, generateMultiStatus } from '../utils/webdavUtils';
import { logger } from '../utils/logger';
import { WebDAVProps } from '../types';
{ WebDAVProps } from '../types';

const SUPPORT_METHODS = ["OPTIONS", "PROPFIND", "MKCOL", "GET", "HEAD", "PUT", "COPY", "MOVE", "DELETE"];
const DAV_CLASS = "1, 2";
Expand All @@ -24,8 +24,8 @@ export async function handleWebDAV(request: Request, bucket: R2Bucket, bucketNam
return await handlePropfind(request, bucket, bucketName);
case "COPY":
return await handleCopy(request, bucket);
case
return await handleMove(request
case "MOVE":
return await handleMove(request, bucket);
default:
return new Response("Method Not Allowed", {
status: 405,
Expand All @@ -41,8 +41,7 @@ export async function handleWebDAV(request: Request, bucket: R2Bucket, bucketNam
}
}

function handleOptions(): Response {
return new Response(null, {
function handleOptions(): Response return new Response(null, {
status: 200,
headers: {
Allow: SUPPORT_METHODS.join(", "),
Expand All @@ -56,7 +55,8 @@ async function handleHead(request: Request, bucket: R2Bucket): Promise<Response>
const object = await bucket.head(resource_path);

if (!object) {
return new Response(null, { status: 404}
return new Response(null, { status: 404 });
}

const headers = new Headers({
"Content-Type": object.httpMetadata?.contentType ?? "application/octet-stream",
Expand All @@ -77,7 +77,7 @@ async function handleGet(request: Request, bucket: R2Bucket, bucketName: string)

const object = await bucket.get(resource_path);
if (!object) {
return new Response("Not Found", { status: 404 });
return new Response("Not Found", { status: });
}

if (object.customMetadata?.resourcetype === "collection") {
Expand Down Expand Up @@ -107,7 +107,8 @@ async function handlePut(request: Request, bucket: R2Bucket): Promise<Response>
try {
const body = await request.arrayBuffer();
await bucket.put(resource_path, body, {
httpMetadata: {: request.headers.get("Content-Type") || "application/octet-stream",
httpMetadata: {
contentType: request.headers.get("Content-Type") || "application/octet-stream",
},
});
return new Response(null, { status: 201 });
Expand All @@ -118,7 +119,7 @@ async function handlePut(request: Request, bucket: R2Bucket): Promise<Response>
}

async function handleDelete(request: Request, bucket: R2Bucket): Promise<Response> {
const resource_path = make_resource_path(request);
const resource_path = make_resource_path);

try {
const object = await bucket.head(resource_path);
Expand All @@ -128,12 +129,11 @@ async function handleDelete(request: Request, bucket: R2Bucket): Promise<Respons

if (object.customMetadata?.resourcetype === "collection") {
// Delete all objects within the directory
for await (const item(bucket, resource_path, true)) {
await bucket.delete(item.key);
for await (const item of listAll(bucket, resource_path, true)) await bucket.delete(item.key);
}
}

await bucket.delete(resource_path);
bucket.delete(resource_path);
return new Response(null, { status: 204 });
} catch (error) {
logger.error("Error deleting object:", error);
Expand All @@ -145,16 +145,16 @@ async function handleMkcol(request: Request, bucket: R2Bucket): Promise<Response
const resource_path = make_resource_path(request);

if (resource_path === "") {
return new Response("Method Not Allowed", { status: 405 });
return new Response("Method Not Allowed", { status: 405 });
}

try {
const exist = await bucket.head(resource_path);
const existingObject = await bucket.head(resource_path);
if (existingObject) {
return new Response("Method Not Allowed", { status: 405 });
}

await bucket.put(resource_path + "/.keep", new Uint8Array(), {
await bucket.put(resource_path +.keep", new Uint8Array(), {
customMetadata: { resourcetype: "collection" }
});
return new Response(null, { status: 201 });
Expand All @@ -164,9 +164,9 @@ async function handleMkcol(request: Request, bucket: R2Bucket): Promise<Response
}
}

async function handlePropfind(request: Request, bucket: R2Bucket, bucketName: string): Promise<Response> {
async function handlefind(request: Request, bucket: R2Bucket, bucketName: string): Promise<Response> {
const resource_path = make_resource_path(request);
const depth.get("Depth") || "infinity";
const depth = request.headers.get("Depth") || "infinity";

try {
const props: WebDAVProps[] = [];
Expand All @@ -179,7 +179,7 @@ async function handlePropfind(request: Request, bucket: R2Bucket, bucketName: st
props.push(fromR2Object(object));

if (depth !== "0" && object.customMetadata?.resourcetype === "collection") {
for await (const item of listAll(bucket, resource_path)) {
for await (const item of listAll(bucket, resource_path {
if (item.key !== resource_path) {
props.push(fromR2Object(item));
}
Expand Down Expand Up @@ -207,7 +207,7 @@ async function handleCopy(request: Request, bucket: R2Bucket): Promise<Response>
const destinationPath = make_resource_path(new Request(destinationUrl));

try {
constObject = await bucket.get(sourcePath);
const sourceObject = await bucket.get(sourcePath);
if (!sourceObject) {
return new Response("Not Found", { status: 404 });
}
Expand All @@ -218,12 +218,12 @@ async function handleCopy(request: Request, bucket: R2Bucket): Promise<Response>
const newPath = item.key.replace(sourcePath, destinationPath);
await bucket.put(newPath, await (await bucket.get(item.key))!.arrayBuffer(), {
httpMetadata: item.httpMetadata,
customMetadata: item.customMetadata
customMetadata: item.customMetadata
});
}
} else {
// Copy file
await bucket.put(destinationPath, sourceObject.body, {
await bucket.put(destinationPath,Object.body, {
httpMetadata: sourceObject.httpMetadata,
customMetadata: sourceObject.customMetadata
});
Expand Down Expand Up @@ -254,14 +254,14 @@ async function handleMove(request: Request, bucket: R2Bucket): Promise<Response>
if (sourceObject.customMetadata?.resourcetype === "collection") {
// Move directory
for await (const item of listAll(bucket, sourcePath, true)) {
const newPath = item.key.replace(sourcePath, destinationPath);
const newPath = item.key.replace(sourcePath,Path);
await bucket.put(newPath, await (await bucket.get(item.key))!.arrayBuffer(), {
httpMetadata: item.httpMetadata,
customMetadata: item.customMetadata
});
await bucket.delete(item.key);
}
} else {
} {
// Move file
await bucket.put(destinationPath, sourceObject.body, {
httpMetadata: sourceObject.httpMetadata,
Expand Down Expand Up @@ -314,7 +314,7 @@ function generateDirectoryListing(bucketName: string, path: string, items: R2Obj
<body>
<h1>Directory Listing for /${bucketName}/${path}</h1>
<ul>
${path !== '' ? '<li><a href="../">📁 .>' : ''}
${path !== '' ? '<li><a href="../">📁 ..</a></li>' : ''}
${listItems}
</ul>
</body>
Expand Down
17 changes: 8 additions & 9 deletions src/utils/webdavUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function fromR2Object(object: R2Object | null): WebDAVProps {
getcontenttype: "application/octet-stream",
getetag: "",
getlastmodified: new Date().toUTCString(),
resourcetype: ""
resourcetype ""
};
}
const isCollection = object.customMetadata?.resourcetype === "collection";
Expand All @@ -42,32 +42,31 @@ export function fromR2Object(object: R2Object | null): WebDAVProps {
};
}

export function make_resource_path(request: Request): string {
export function_resource_path(request: Request): string {
let path = new URL(request.url).pathname.slice(1);
return path.endsWith("/") ? path.slice(0, -1) : path;
}

export function generatePropfindResponse(bucketName: string, basePath: string, props: WebDAVProps[]): string {
const xml = `<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:">
const xml = `xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D=":">
${props.map(prop => generatePropResponse(bucketName, basePath, prop)).join('\n')}
</D:multistatus>`;
return xml;
}

function generatePropResponse(bucketName: string, basePath: string, prop: WebDAVProps): string {
const resourcePath = `/${bucketName}/${basePath}${prop.displayname ? '/' + prop.displayname : ''}`.replace(/\/+/g, '/');
const resourcePath = `/${bucketName}/${basePath}${prop.displayname ? '/' + prop.displayname : ''}`.replace\/+/g, '/');
return ` <D:response>
<D:href>${resourcePath}</D:href>
<D:propstat>
<D:prop>
<D:creationdate>${prop.creationdate}</D:creationdate>
<D:displayname>${prop.displayname}</D:displayname>
<D:creationdate>${prop.creationdate}</D:creationdate <D:displayname>${prop.displayname}</D:displayname>
<D:getcontentlanguage>${prop.getcontentlanguage || ''}</D:getcontentlanguage>
<D:getcontentlength>${prop.getcontentlength}</D:getcontentlength>
<D:getcontenttype>${prop.getcontenttype || ''}</D:getcontenttype>
<D:getetag>${prop.getetag || ''}</D:getetag>
<D:getlastmodified>${prop.getlastmodified}</D:getlastmodified>
<D:getlastmodified>${prop.getlastmodified}</Dlastmodified>
<D:resourcetype>${prop.resourcetype === 'collection' ? '<D:collection/>' : ''}</D:resourcetype>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
Expand All @@ -76,7 +75,7 @@ function generatePropResponse(bucketName: string, basePath: string, prop: WebDAV
}

export function generateMultiStatus(responses: string[]): string {
return `<?xml version="1.0" encoding="utf-8"?>
return `xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:">
${responses.join('\n')}
</D:multistatus>`;
Expand Down

0 comments on commit 2c03f37

Please sign in to comment.