From 2eae791a33d72ec2eab1af267ce8e40a37456d7a Mon Sep 17 00:00:00 2001 From: abersheeran Date: Mon, 18 Dec 2023 16:06:01 +0800 Subject: [PATCH] Refactor code to improve performance and readability --- src/index.ts | 258 ++++++++++++++++----------------------------------- 1 file changed, 81 insertions(+), 177 deletions(-) diff --git a/src/index.ts b/src/index.ts index cdc5414..b13fb27 100644 --- a/src/index.ts +++ b/src/index.ts @@ -76,14 +76,14 @@ type DavProperties = { function fromR2Object(object: R2Object | null | undefined): DavProperties { if (object === null || object === undefined) { return { - creationdate: undefined, + creationdate: new Date().toUTCString(), displayname: undefined, getcontentlanguage: undefined, - getcontentlength: undefined, + getcontentlength: "0", getcontenttype: undefined, getetag: undefined, - getlastmodified: undefined, - resourcetype: '', + getlastmodified: new Date().toUTCString(), + resourcetype: "", }; } @@ -101,7 +101,9 @@ function fromR2Object(object: R2Object | null | undefined): DavProperties { function make_resource_path(request: Request): string { - return new URL(request.url).pathname.slice(1) + let path = new URL(request.url).pathname.slice(1); + path = path.endsWith('/') ? path.slice(0, -1) : path; + return path; } async function handle_options(request: Request, bucket: R2Bucket): Promise { @@ -180,12 +182,12 @@ async function handle_get(request: Request, bucket: R2Bucket): Promise } async function handle_put(request: Request, bucket: R2Bucket): Promise { - let resource_path = make_resource_path(request); - - if (resource_path.endsWith('/')) { + if (request.url.endsWith('/')) { return new Response('Method Not Allowed', { status: 405 }); } + let resource_path = make_resource_path(request); + // Check if the parent directory exists let dirpath = resource_path.split('/').slice(0, -1).join('/'); if (dirpath !== '') { @@ -205,7 +207,6 @@ async function handle_put(request: Request, bucket: R2Bucket): Promise async function handle_delete(request: Request, bucket: R2Bucket): Promise { let resource_path = make_resource_path(request); - resource_path = resource_path.endsWith('/') ? resource_path.slice(0, -1) : resource_path; if (resource_path === '') { let r2_objects, cursor: string | undefined = undefined; @@ -258,7 +259,6 @@ async function handle_mkcol(request: Request, bucket: R2Bucket): Promise { let resource_path = make_resource_path(request); - let depth = request.headers.get('Depth') ?? 'infinity'; - switch (depth) { - case '0': { - if (resource_path === "") { - return new Response(` - + + let is_collection: boolean; + let page = ` +`; + + if (resource_path === "") { + page += ` / - - - HTTP/1.1 200 OK - - - -`, { - status: 207, - headers: { - 'Content-Type': 'text/xml', - }, - }); - } - - let object = await bucket.head(resource_path); - if (object === null && resource_path.endsWith('/')) { - object = await bucket.head(resource_path.slice(0, -1)); - } - - if (object === null) { - return new Response('Not Found', { status: 404 }); - } - - let page = ` - - - /${resource_path} - - - ${Object.entries(fromR2Object(object)) - .filter(([_, value]) => value !== undefined) - .map(([key, value]) => `<${key}>${value}`) - .join('\n') - } - - HTTP/1.1 200 OK - - - -`; - return new Response(page, { - status: 207, - headers: { - 'Content-Type': 'text/xml', - }, - }); - } - case '1': { - if (resource_path !== "") { - let object = await bucket.head(resource_path); - if (object === null && resource_path.endsWith('/')) { - object = await bucket.head(resource_path.slice(0, -1)); - } - - if (object === null) { - return new Response('Not Found', { status: 404 }); - } - - if (object.customMetadata?.resourcetype !== '') { - let page = ` - - - /${resource_path} - - - ${Object.entries(fromR2Object(object)) - .filter(([_, value]) => value !== undefined) - .map(([key, value]) => `<${key}>${value}`) - .join('\n ') - } - - HTTP/1.1 200 OK - - - - `; - return new Response(page, { - status: 207, - headers: { - 'Content-Type': 'text/xml', - }, - }); - } - } - - let page = ` -`; - - let prefix = resource_path.endsWith('/') || resource_path === "" ? resource_path : resource_path + '/'; - for await (let object of listAll(bucket, prefix)) { - let href = `/${object.key + (object.customMetadata?.resourcetype === '' ? '/' : '')}`; - page += ` - - ${href} - - - ${Object.entries(fromR2Object(object)) - .filter(([_, value]) => value !== undefined) - .map(([key, value]) => `<${key}>${value}`) - .join('\n ') - } + ${Object.entries(fromR2Object(null)) + .filter(([_, value]) => value !== undefined) + .map(([key, value]) => `<${key}>${value}`) + .join('\n')} HTTP/1.1 200 OK `; - } - - page += '\n\n'; - return new Response(page, { - status: 207, - headers: { - 'Content-Type': 'text/xml', - }, - }); + is_collection = true; + } else { + let object = await bucket.head(resource_path); + if (object === null) { + return new Response('Not Found', { status: 404 }); } - case 'infinity': { - if (resource_path !== "") { - let object = await bucket.head(resource_path); - if (object === null && resource_path.endsWith('/')) { - object = await bucket.head(resource_path.slice(0, -1)); - } - - if (object === null) { - return new Response('Not Found', { status: 404 }); - } - - if (object.customMetadata?.resourcetype !== '') { - let page = ` - + is_collection = object.customMetadata?.resourcetype === ''; + let href = `/${object.key + (object.customMetadata?.resourcetype === '' ? '/' : '')}`; + page += ` - /${resource_path} + ${href} + + + ${Object.entries(fromR2Object(object)) + .filter(([_, value]) => value !== undefined) + .map(([key, value]) => `<${key}>${value}`) + .join('\n')} + + HTTP/1.1 200 OK + + ` + }; + + if (is_collection) { + let depth = request.headers.get('Depth') ?? 'infinity'; + switch (depth) { + case '0': break; + case '1': { + let prefix = resource_path === "" ? resource_path : resource_path + '/'; + for await (let object of listAll(bucket, prefix)) { + let href = `/${object.key + (object.customMetadata?.resourcetype === '' ? '/' : '')}`; + page += ` + + ${href} ${Object.entries(fromR2Object(object)) @@ -433,52 +345,44 @@ async function handle_propfind(request: Request, bucket: R2Bucket): Promise HTTP/1.1 200 OK - - -`; - return new Response(page, { - status: 207, - headers: { - 'Content-Type': 'text/xml', - }, - }); + `; } } - - let page = ` -`; - - let prefix = resource_path.endsWith('/') || resource_path === "" ? resource_path : resource_path + '/'; - for await (let object of listAll(bucket, prefix, true)) { - let href = `/${object.key + (object.customMetadata?.resourcetype === '' ? '/' : '')}`; - page += ` + break; + case 'infinity': { + let prefix = resource_path === "" ? resource_path : resource_path + '/'; + for await (let object of listAll(bucket, prefix, true)) { + let href = `/${object.key + (object.customMetadata?.resourcetype === '' ? '/' : '')}`; + page += ` ${href} ${Object.entries(fromR2Object(object)) - .filter(([_, value]) => value !== undefined) - .map(([key, value]) => `<${key}>${value}`) - .join('\n ') - } + .filter(([_, value]) => value !== undefined) + .map(([key, value]) => `<${key}>${value}`) + .join('\n ') + } HTTP/1.1 200 OK `; + } + } + break; + default: { + return new Response('Forbidden', { status: 403 }); } - - page += '\n\n'; - return new Response(page, { - status: 207, - headers: { - 'Content-Type': 'text/xml', - }, - }); - } - default: { - return new Response('Forbidden', { status: 403 }); } } + + page += '\n\n'; + return new Response(page, { + status: 207, + headers: { + 'Content-Type': 'text/xml', + }, + }); } async function handle_copy(request: Request, bucket: R2Bucket): Promise { @@ -503,7 +407,7 @@ async function handle_copy(request: Request, bucket: R2Bucket): Promise { let target = destination + "/" + object.key.slice(prefix.length); target = target.endsWith("/") ? target.slice(0, -1) : target; @@ -595,7 +499,7 @@ async function handle_move(request: Request, bucket: R2Bucket): Promise { let target = destination + "/" + object.key.slice(prefix.length); target = target.endsWith("/") ? target.slice(0, -1) : target;