Skip to content

Commit a3faad1

Browse files
committed
chore: webdav逻辑调整,减少冗余代码
1 parent 2ce24e5 commit a3faad1

35 files changed

+938
-3708
lines changed

backend/docker-server.js

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import { checkAndInitDatabase } from "./src/utils/database.js";
1818
import app from "./src/index.js";
1919
import { ApiStatus } from "./src/constants/index.js";
2020

21-
import { getWebDAVConfig, getPlatformConfig } from "./src/webdav/auth/index.js";
21+
import { setExpressWebDAVHeaders } from "./src/webdav/utils/headerUtils.js";
22+
import { getWebDAVConfig } from "./src/webdav/auth/config/WebDAVConfig.js";
2223

2324
// ES模块兼容性处理:获取__dirname
2425
const __filename = fileURLToPath(import.meta.url);
@@ -222,9 +223,6 @@ function createErrorResponse(error, status = ApiStatus.INTERNAL_ERROR, defaultMe
222223
const server = express();
223224
const PORT = process.env.PORT || 8787;
224225

225-
// 获取Express平台配置(仅用于代理设置)
226-
const platformConfig = getPlatformConfig("express");
227-
228226
// 数据目录和数据库设置
229227
const dataDir = process.env.DATA_DIR || path.join(__dirname, "data");
230228
if (!fs.existsSync(dataDir)) {
@@ -245,28 +243,22 @@ let isDbInitialized = false;
245243
// 获取WebDAV配置
246244
const webdavConfig = getWebDAVConfig();
247245

248-
// 应用Express平台配置
249-
if (platformConfig.TRUST_PROXY) {
250-
server.set("trust proxy", true);
251-
console.log("Express: 已启用代理信任");
252-
}
253-
254-
// CORS配置 - 使用统一配置
246+
// CORS配置
255247
const corsOptions = {
256-
origin: webdavConfig.CORS.ALLOW_ORIGIN,
257-
methods: webdavConfig.SUPPORTED_METHODS.join(","),
248+
origin: "*",
249+
methods: webdavConfig.METHODS.join(","),
258250
credentials: true,
259251
optionsSuccessStatus: 204,
260252
maxAge: 86400,
261-
exposedHeaders: webdavConfig.CORS.ALLOW_HEADERS,
253+
exposedHeaders: webdavConfig.HEADERS["Access-Control-Expose-Headers"],
262254
};
263255

264256
// ==========================================
265257
// 中间件和服务器配置
266258
// ==========================================
267259

268260
// 明确告知Express处理WebDAV方法
269-
webdavConfig.SUPPORTED_METHODS.forEach((method) => {
261+
webdavConfig.METHODS.forEach((method) => {
270262
server[method.toLowerCase()] = function (path, ...handlers) {
271263
return server.route(path).all(function (req, res, next) {
272264
if (req.method === method) {
@@ -278,7 +270,7 @@ webdavConfig.SUPPORTED_METHODS.forEach((method) => {
278270
});
279271

280272
// 为WebDAV方法添加直接路由,确保它们能被正确处理
281-
webdavConfig.SUPPORTED_METHODS.forEach((method) => {
273+
webdavConfig.METHODS.forEach((method) => {
282274
server[method.toLowerCase()]("/dav*", (req, res, next) => {
283275
logMessage("debug", `直接WebDAV路由处理: ${method} ${req.path}`);
284276
next();
@@ -291,10 +283,11 @@ webdavConfig.SUPPORTED_METHODS.forEach((method) => {
291283

292284
// 1. 基础中间件 - CORS和HTTP方法处理
293285
// ==========================================
294-
// 智能CORS处理:跳过WebDAV OPTIONS请求,让后续中间件处理
286+
// 智能CORS处理:跳过WebDAV OPTIONS请求和根路径OPTIONS请求,让后续中间件处理
295287
server.use((req, res, next) => {
296-
// 对于WebDAV路径的OPTIONS请求,跳过CORS自动处理
297-
if (req.method === "OPTIONS" && (req.path === "/dav" || req.path.startsWith("/dav/"))) {
288+
// 对于WebDAV路径和根路径的OPTIONS请求,跳过CORS自动处理
289+
if (req.method === "OPTIONS" && (req.path === "/" || req.path === "/dav" || req.path.startsWith("/dav/"))) {
290+
logMessage("debug", `跳过CORS处理: ${req.method} ${req.path}`);
298291
return next();
299292
}
300293
// 其他请求使用标准CORS处理
@@ -305,11 +298,11 @@ server.use(methodOverride("X-HTTP-Method"));
305298
server.use(methodOverride("X-Method-Override"));
306299
server.disable("x-powered-by");
307300

308-
// WebDAV基础方法支持 - 使用统一配置
301+
// WebDAV基础方法支持
309302
server.use((req, res, next) => {
310303
if (req.path === "/dav" || req.path.startsWith("/dav/")) {
311-
res.setHeader("Access-Control-Allow-Methods", webdavConfig.SUPPORTED_METHODS.join(","));
312-
res.setHeader("Allow", webdavConfig.SUPPORTED_METHODS.join(","));
304+
// 使用统一的WebDAV头部设置工具
305+
setExpressWebDAVHeaders(res);
313306

314307
// 区分CORS预检请求和WebDAV OPTIONS请求
315308
if (req.method === "OPTIONS") {
@@ -319,12 +312,6 @@ server.use((req, res, next) => {
319312
if (isCORSPreflight) {
320313
// CORS预检请求:在Express层直接处理
321314
return res.status(204).end();
322-
} else {
323-
// WebDAV OPTIONS请求:传递给Hono层处理认证和能力发现
324-
// 添加WebDAV特定的响应头(为了兼容性)
325-
res.setHeader("DAV", webdavConfig.PROTOCOL.RESPONSE_HEADERS.DAV);
326-
res.setHeader("MS-Author-Via", webdavConfig.PROTOCOL.RESPONSE_HEADERS["MS-Author-Via"]);
327-
// 继续传递给Hono层处理
328315
}
329316
}
330317
}
@@ -505,7 +492,7 @@ server.use((req, res, next) => {
505492
// WebDAV请求日志记录 - 认证由Hono层处理
506493
server.use("/dav", (req, res, next) => {
507494
// 明确设置允许的方法
508-
res.setHeader("Allow", webdavConfig.SUPPORTED_METHODS.join(","));
495+
res.setHeader("Allow", webdavConfig.METHODS.join(","));
509496

510497
// 记录WebDAV请求信息
511498
logMessage("info", `WebDAV请求: ${req.method} ${req.path}`, {
@@ -549,6 +536,25 @@ server.use(async (req, res, next) => {
549536
// 路由处理
550537
// ==========================================
551538

539+
// 根路径WebDAV OPTIONS兼容性处理器
540+
// 为1Panel等客户端提供WebDAV能力发现支持
541+
server.options("/", (req, res) => {
542+
// 返回标准WebDAV能力声明,与/dav路径保持一致
543+
const headers = {
544+
Allow: "OPTIONS, PROPFIND, GET, HEAD, PUT, DELETE, MKCOL, COPY, MOVE, LOCK, UNLOCK, PROPPATCH",
545+
DAV: "1, 2",
546+
"MS-Author-Via": "DAV",
547+
"Access-Control-Allow-Origin": "*",
548+
"Access-Control-Allow-Methods": "OPTIONS, PROPFIND, GET, HEAD, PUT, DELETE, MKCOL, COPY, MOVE, LOCK, UNLOCK, PROPPATCH",
549+
"Access-Control-Allow-Headers": "Authorization, Content-Type, Depth, Destination, If, Lock-Token, Overwrite, X-Custom-Auth-Key",
550+
"Access-Control-Expose-Headers": "DAV, Lock-Token, MS-Author-Via",
551+
"Access-Control-Max-Age": "86400",
552+
};
553+
554+
logMessage("info", "根路径WebDAV OPTIONS请求 - 客户端兼容性支持");
555+
res.set(headers).status(200).end();
556+
});
557+
552558
// 通配符路由 - 处理所有其他API请求
553559
server.use("*", async (req, res) => {
554560
try {

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cloudpaste-api",
3-
"version": "0.8.0",
3+
"version": "0.8.1",
44
"description": "CloudPaste API基于Cloudflare Workers和D1数据库",
55
"main": "workers.js",
66
"scripts": {

backend/src/index.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ import { WEBDAV_BASE_PATH } from "./webdav/auth/config/WebDAVConfig.js";
3232
// 统一CORS中间件
3333
app.use("*", async (c, next) => {
3434
const isWebDAVPath = c.req.path === WEBDAV_BASE_PATH || c.req.path.startsWith(WEBDAV_BASE_PATH + "/");
35+
const isRootPath = c.req.path === "/";
3536

36-
if (c.req.method === "OPTIONS" && isWebDAVPath) {
37-
// WebDAV OPTIONS请求跳过CORS自动处理,进入WebDAV认证流程
38-
console.log("WebDAV OPTIONS请求,进入认证流程:", c.req.path);
37+
if (c.req.method === "OPTIONS" && (isWebDAVPath || isRootPath)) {
38+
// WebDAV OPTIONS请求和根路径OPTIONS请求跳过CORS自动处理
39+
console.log("WebDAV OPTIONS请求:", c.req.method, c.req.path);
3940
await next();
4041
return;
4142
} else {
@@ -69,6 +70,26 @@ app.use("*", async (c, next) => {
6970
}
7071
});
7172

73+
// 根路径WebDAV OPTIONS兼容性处理器
74+
// 为1Panel等客户端提供WebDAV能力发现支持
75+
// 必须在其他路由注册之前,确保优先匹配
76+
app.options("/", (c) => {
77+
// 返回标准WebDAV能力声明,与/dav路径保持一致
78+
const headers = {
79+
Allow: "OPTIONS, PROPFIND, GET, HEAD, PUT, DELETE, MKCOL, COPY, MOVE, LOCK, UNLOCK, PROPPATCH",
80+
DAV: "1, 2",
81+
"MS-Author-Via": "DAV",
82+
"Access-Control-Allow-Origin": "*",
83+
"Access-Control-Allow-Methods": "OPTIONS, PROPFIND, GET, HEAD, PUT, DELETE, MKCOL, COPY, MOVE, LOCK, UNLOCK, PROPPATCH",
84+
"Access-Control-Allow-Headers": "Authorization, Content-Type, Depth, Destination, If, Lock-Token, Overwrite, X-Custom-Auth-Key",
85+
"Access-Control-Expose-Headers": "DAV, Lock-Token, MS-Author-Via",
86+
"Access-Control-Max-Age": "86400",
87+
};
88+
89+
console.log("根路径WebDAV OPTIONS请求 - 客户端兼容性支持");
90+
return new Response("", { status: 200, headers });
91+
});
92+
7293
// 注册路由
7394
app.route("/", adminRoutes);
7495
app.route("/", apiKeyRoutes);

backend/src/middlewares/authGatewayMiddleware.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ async function performAuthentication(c) {
108108
const authHeader = c.req.header("Authorization");
109109
authResult = await authService.authenticate(authHeader);
110110

111-
// 如果标准认证失败,尝试自定义授权头(向后兼容)
111+
// 如果标准认证失败,尝试自定义授权头
112112
if (!authResult.isAuthenticated) {
113113
const customAuthKey = c.req.header("X-Custom-Auth-Key");
114114
if (customAuthKey) {
@@ -250,6 +250,17 @@ const gatewayUtils = {
250250
return authResult.isAdmin() ? "admin" : "apikey";
251251
},
252252

253+
/**
254+
* 获取用户类型(类型系统用)
255+
*/
256+
getUserType: (c) => {
257+
const authResult = c.get("authResult");
258+
if (!authResult || !authResult.isAuthenticated) {
259+
return null;
260+
}
261+
return authResult.getUserType();
262+
},
263+
253264
/**
254265
* 检查操作权限(委托给认证服务)
255266
*/
@@ -486,3 +497,8 @@ authGateway.utils = gatewayUtils;
486497
* 创建认证服务实例
487498
*/
488499
authGateway.createAuthService = createAuthService;
500+
501+
/**
502+
* 执行认证处理 - 供WebDAV等协议层调用
503+
*/
504+
authGateway.performAuth = performAuthentication;

backend/src/routes/systemRoutes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ systemRoutes.get("/api/version", async (c) => {
6868
const isDocker = runtimeEnv === "docker";
6969

7070
// 统一的默认版本配置
71-
const DEFAULT_VERSION = "0.8.0";
71+
const DEFAULT_VERSION = "0.8.1";
7272
const DEFAULT_NAME = "cloudpaste-api";
7373

7474
let version = DEFAULT_VERSION;

backend/src/routes/webdavRoutes.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* WebDAV路由定义 - 支持配置化路径
2+
* WebDAV路由定义
33
*/
44
import { Hono } from "hono";
55
import { webdavAuthMiddleware, handleWebDAV } from "../webdav/index.js";
@@ -10,7 +10,7 @@ import { createErrorResponse } from "../utils/common.js";
1010
// 创建WebDAV路由处理程序
1111
const webdavRoutes = new Hono();
1212

13-
// WebDAV认证中间件应用到WebDAV路径
13+
// WebDAV认证和权限检查
1414
webdavRoutes.use(WEBDAV_BASE_PATH, webdavAuthMiddleware);
1515
webdavRoutes.use(`${WEBDAV_BASE_PATH}/*`, webdavAuthMiddleware);
1616

backend/src/services/authService.js

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,20 @@ export class AuthResult {
5151
return this.userId;
5252
}
5353

54+
/**
55+
* 获取用户类型
56+
* WebDAV认证需要的方法
57+
*/
58+
getUserType() {
59+
if (this._isAdmin) {
60+
return "admin";
61+
}
62+
if (this.keyInfo) {
63+
return "apiKey";
64+
}
65+
return "unknown";
66+
}
67+
5468
/**
5569
* 检查是否有任一权限
5670
* 网关权限验证需要的方法
@@ -259,16 +273,22 @@ export class AuthService {
259273
return new AuthResult();
260274
}
261275

276+
let result;
262277
switch (type) {
263278
case "bearer":
264-
return await this.validateAdminAuth(token);
279+
result = await this.validateAdminAuth(token);
280+
break;
265281
case "apikey":
266-
return await this.validateApiKeyAuth(token);
282+
result = await this.validateApiKeyAuth(token);
283+
break;
267284
case "basic":
268-
return await this.validateBasicAuth(token);
285+
result = await this.validateBasicAuth(token);
286+
break;
269287
default:
270-
return new AuthResult();
288+
result = new AuthResult();
271289
}
290+
291+
return result;
272292
}
273293

274294
/**

0 commit comments

Comments
 (0)