From e161610ca31be03451c24a077749f306d85a41fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ai=E5=90=9B?= Date: Thu, 12 Sep 2024 04:44:22 +0000 Subject: [PATCH] ok-4-1 --- src/handlers/requestHandler.ts | 5 ++- src/handlers/webdavHandler.ts | 81 ++++++++++++++++++++-------------- src/index.ts | 1 + src/types.ts | 3 +- src/utils/auth.ts | 9 ++-- src/utils/cors.ts | 5 ++- src/utils/logger.ts | 1 + src/utils/webdavUtils.ts | 9 ++-- 8 files changed, 65 insertions(+), 49 deletions(-) diff --git a/src/handlers/requestHandler.ts b/src/handlers/requestHandler.ts index af41a92..f65382a 100644 --- a/src/handlers/requestHandler.ts +++ b/src/handlers/requestHandler.ts @@ -15,7 +15,8 @@ export async function handleRequest(request: Request, env: Env, ctx: ExecutionCo }); } - const response = await handleWebDAV(request, env.BUCKET, env.BUCKET_NAME); + // 直接传递整个 env 对象给 handleWebDAV + const response = await handleWebDAV(request, env); setCORSHeaders(response, request); return response; @@ -23,4 +24,4 @@ export async function handleRequest(request: Request, env: Env, ctx: ExecutionCo logger.error("Error in request handling:", error); return new Response("Internal Server Error", { status: 500 }); } -} \ No newline at end of file +} diff --git a/src/handlers/webdavHandler.ts b/src/handlers/webdavHandler.ts index bb49f3b..5799057 100644 --- a/src/handlers/webdavHandler.ts +++ b/src/handlers/webdavHandler.ts @@ -1,32 +1,37 @@ +// 文件名:src/handlers/webdavHandler.ts import { listAll, fromR2Object, make_resource_path, generatePropfindResponse } from '../utils/webdavUtils'; import { logger } from '../utils/logger'; import { generateHTML, generateErrorHTML } from '../utils/templates'; -import { WebDAVProps } from '../types'; +import { WebDAVProps, Env } from '../types'; +import { authenticate } from '../utils/auth'; const SUPPORT_METHODS = ["OPTIONS", "PROPFIND", "MKCOL", "GET", "HEAD", "PUT", "COPY", "MOVE", "DELETE"]; const DAV_CLASS = "1, 2"; -export async function handleWebDAV(request: Request, bucket: R2Bucket, bucketName: string): Promise { +export async function handleWebDAV(request: Request, env: Env): Promise { + const { BUCKET, BUCKET_NAME } = env; // 从 env 中获取 BUCKET 和 BUCKET_NAME + try { switch (request.method) { + // 原来的处理逻辑不变 case "OPTIONS": return handleOptions(); case "HEAD": - return await handleHead(request, bucket); + return await handleHead(request, BUCKET); case "GET": - return await handleGet(request, bucket, bucketName); + return await handleGet(request, BUCKET, BUCKET_NAME); case "PUT": - return await handlePut(request, bucket); + return await handlePut(request, BUCKET); case "DELETE": - return await handleDelete(request, bucket); + return await handleDelete(request, BUCKET); case "MKCOL": - return await handleMkcol(request, bucket); + return await handleMkcol(request, BUCKET); case "PROPFIND": - return await handlePropfind(request, bucket, bucketName); + return await handlePropfind(request, BUCKET, BUCKET_NAME); case "COPY": - return await handleCopy(request, bucket); + return await handleCopy(request, BUCKET); case "MOVE": - return await handleMove(request, bucket); + return await handleMove(request, BUCKET); default: return new Response("Method Not Allowed", { status: 405, @@ -36,8 +41,9 @@ export async function handleWebDAV(request: Request, bucket: R2Bucket, bucketNam } }); } - } catch (error) { const err = error as Error; - logger.error("Error in WebDAV handling:", error); + } catch (error) { + const err = error as Error; + logger.error("Error in WebDAV handling:", err.message); return new Response(generateErrorHTML("Internal Server Error", err.message), { status: 500, headers: { "Content-Type": "text/html; charset=utf-8" } @@ -50,7 +56,13 @@ function handleOptions(): Response { status: 200, headers: { Allow: SUPPORT_METHODS.join(", "), - DAV: DAV_CLASS + DAV: DAV_CLASS, + "Access-Control-Allow-Methods": SUPPORT_METHODS.join(", "), + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Headers": "Authorization, Content-Type, Depth, Overwrite, Destination, Range", + "Access-Control-Expose-Headers": "Content-Type, Content-Length, DAV, ETag, Last-Modified, Location, Date, Content-Range", + "Access-Control-Allow-Credentials": "true", + "Access-Control-Max-Age": "86400" } }); } @@ -78,10 +90,8 @@ async function handleGet(request: Request, bucket: R2Bucket, bucketName: string) const resource_path = make_resource_path(request); if (request.url.endsWith("/")) { - // 处理目录 return await handleDirectory(bucket, resource_path, bucketName); } else { - // 处理文件 return await handleFile(bucket, resource_path); } } @@ -101,8 +111,9 @@ async function handleDirectory(bucket: R2Bucket, resource_path: string, bucketNa const href = `/${object.key}${isDirectory ? "/" : ""}`; items.push({ name: `${isDirectory ? '📁 ' : '📄 '}${displayName}`, href }); } - } catch (error) { const err = error as Error; - logger.error("Error listing objects:", error); + } catch (error) { + const err = error as Error; + logger.error("Error listing objects:", err.message); return new Response(generateErrorHTML("Error listing directory contents", err.message), { status: 500, headers: { "Content-Type": "text/html; charset=utf-8" } @@ -131,8 +142,9 @@ async function handleFile(bucket: R2Bucket, resource_path: string): Promise }, }); return new Response("Created", { status: 201 }); - } catch (error) { const err = error as Error; - logger.error("Error uploading file:", error); + } catch (error) { + const err = error as Error; + logger.error("Error uploading file:", err.message); return new Response(generateErrorHTML("Error uploading file", err.message), { status: 500, headers: { "Content-Type": "text/html; charset=utf-8" } @@ -166,8 +179,9 @@ async function handleDelete(request: Request, bucket: R2Bucket): Promise }); return new Response("Created", { status: 201 }); - } catch (error) { const err = error as Error; - logger.error("Error copying object:", error); + } catch (error) { + const err = error as Error; + logger.error("Error copying object:", err.message); return new Response(generateErrorHTML("Error copying file", err.message), { status: 500, headers: { "Content-Type": "text/html; charset=utf-8" } @@ -283,8 +299,9 @@ async function handleMove(request: Request, bucket: R2Bucket): Promise await bucket.delete(sourcePath); return new Response("No Content", { status: 204 }); - } catch (error) { const err = error as Error; - logger.error("Error moving object:", error); + } catch (error) { + const err = error as Error; + logger.error("Error moving object:", err.message); return new Response(generateErrorHTML("Error moving file", err.message), { status: 500, headers: { "Content-Type": "text/html; charset=utf-8" } diff --git a/src/index.ts b/src/index.ts index 0156421..a8c6f11 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +// 文件名:src/index.ts import { handleRequest } from './handlers/requestHandler'; import { Env } from './types'; diff --git a/src/types.ts b/src/types.ts index 85f7af7..871242e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,8 +1,9 @@ +// 文件名:src/types.ts export interface Env { BUCKET: R2Bucket; USERNAME: string; PASSWORD: string; - BUCKET_NAME: string; // 新增的环境变量 + BUCKET_NAME: string; } export interface CacheableResponse { diff --git a/src/utils/auth.ts b/src/utils/auth.ts index bc5d79e..d954000 100644 --- a/src/utils/auth.ts +++ b/src/utils/auth.ts @@ -1,3 +1,4 @@ +// 文件名:src/utils/auth.ts import { Env } from '../types'; export function authenticate(request: Request, env: Env): boolean { @@ -11,10 +12,6 @@ export function authenticate(request: Request, env: Env): boolean { return false; } - try { - const [username, password] = atob(authValue).split(':'); - return username === env.USERNAME && password === env.PASSWORD; - } catch (e) { - return false; - } + const [username, password] = atob(authValue).split(':'); + return username === env.USERNAME && password === env.PASSWORD; } diff --git a/src/utils/cors.ts b/src/utils/cors.ts index eff5aab..3c8454e 100644 --- a/src/utils/cors.ts +++ b/src/utils/cors.ts @@ -1,3 +1,4 @@ +// 文件名:src/utils/cors.ts export function setCORSHeaders(response: Response, request: Request): void { const origin = request.headers.get("Origin"); if (origin) { @@ -8,5 +9,5 @@ export function setCORSHeaders(response: Response, request: Request): void { response.headers.set("Access-Control-Allow-Headers", "Authorization, Content-Type, Depth, Overwrite, Destination, Range"); response.headers.set("Access-Control-Expose-Headers", "Content-Type, Content-Length, DAV, ETag, Last-Modified, Location, Date, Content-Range"); response.headers.set("Access-Control-Allow-Credentials", "true"); - response.headers.set("Access-Control-Max-Age", "86400"); // Cache preflight for 24 hours -} + response.headers.set("Access-Control-Max-Age", "86400"); +} \ No newline at end of file diff --git a/src/utils/logger.ts b/src/utils/logger.ts index a876caf..ea1b39f 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -1,3 +1,4 @@ +// 文件名:src/utils/logger.ts export const logger = { info: (message: string, ...args: any[]) => console.log(`[INFO] ${new Date().toISOString()} - ${message}`, ...args), error: (message: string, ...args: any[]) => console.error(`[ERROR] ${new Date().toISOString()} - ${message}`, ...args), diff --git a/src/utils/webdavUtils.ts b/src/utils/webdavUtils.ts index 1ec53c5..f72493f 100644 --- a/src/utils/webdavUtils.ts +++ b/src/utils/webdavUtils.ts @@ -1,13 +1,10 @@ +// 文件名:src/utils/webdavUtils.ts import { R2Object } from '@cloudflare/workers-types'; import { WebDAVProps } from '../types'; export function make_resource_path(request: Request): string { const url = new URL(request.url); - let path = decodeURIComponent(url.pathname.slice(1)); // 移除初始的 '/' - - // 处理 Windows 特殊字符 - path = path.replace(/\\/g, '/'); - return path; + return decodeURIComponent(url.pathname.slice(1)); } export async function* listAll(bucket: R2Bucket, prefix: string) { @@ -76,4 +73,4 @@ function generatePropResponse(bucketName: string, basePath: string, prop: WebDAV HTTP/1.1 200 OK `; -} +} \ No newline at end of file