From 38c5d1e6224417f3c0c5b22b29d07b1390669a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=BD=AE?= Date: Mon, 9 Mar 2026 18:51:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=96=B9=E6=A1=88=EF=BC=9A?= =?UTF-8?q?=E5=9C=A8=20routes/webdav.py=20=E4=B8=AD=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=BA=86=E4=B8=80=E4=B8=AA=20WSGI=20=E4=B8=AD=E9=97=B4?= =?UTF-8?q?=E4=BB=B6=E5=8C=85=E8=A3=85=E5=87=BD=E6=95=B0=EF=BC=8C=E5=9C=A8?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=88=B0=E8=BE=BE=20WsgiDAV=20=E5=89=8D?= =?UTF-8?q?=EF=BC=9A=20=20=201.=20=E8=AF=BB=E5=8F=96=20X-Forwarded-Proto?= =?UTF-8?q?=20=E8=AE=BE=E7=BD=AE=E6=AD=A3=E7=A1=AE=E7=9A=84=20wsgi.url=5Fs?= =?UTF-8?q?cheme=20=20=202.=20=E5=B0=86=20Destination=20=E5=A4=B4=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E5=A4=96=E9=83=A8=20scheme/host=20=E9=87=8D=E5=86=99?= =?UTF-8?q?=E4=B8=BA=E5=86=85=E9=83=A8=E5=AE=9E=E9=99=85=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- routes/webdav.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/routes/webdav.py b/routes/webdav.py index a1a655e..c89745d 100644 --- a/routes/webdav.py +++ b/routes/webdav.py @@ -6,6 +6,7 @@ WebDAV 文件管理路由 """ from pathlib import Path +from urllib.parse import urlparse, urlunparse from wsgidav.wsgidav_app import WsgiDAVApp from wsgidav.fs_dav_provider import FilesystemProvider @@ -56,4 +57,36 @@ config = { }, } -wsgidav_app = WsgiDAVApp(config) +_wsgidav_app = WsgiDAVApp(config) + + +def wsgidav_app(environ, start_response): + """WSGI 中间件:处理反向代理场景下 Destination 头的 scheme/host 不匹配问题。 + + 当服务运行在 HTTPS 反向代理后面时,客户端发送的 Destination 头包含外部 URL + (如 https://example.com/webdav/docs/new-name),但 WsgiDAV 内部看到的是 HTTP。 + 这个中间件将 Destination 头重写为与内部请求一致的 scheme 和 host。 + """ + # 从 X-Forwarded 头获取外部信息,并确保 wsgi.url_scheme 正确 + forwarded_proto = environ.get("HTTP_X_FORWARDED_PROTO") + if forwarded_proto: + environ["wsgi.url_scheme"] = forwarded_proto + + # 重写 Destination 头:将外部 scheme/host 替换为内部实际值 + destination = environ.get("HTTP_DESTINATION") + if destination: + parsed = urlparse(destination) + # 用内部实际的 scheme 和 host 替换 + internal_scheme = environ.get("wsgi.url_scheme", "http") + internal_host = environ.get("HTTP_HOST", environ.get("SERVER_NAME", "localhost")) + rewritten = urlunparse(( + internal_scheme, + internal_host, + parsed.path, + parsed.params, + parsed.query, + parsed.fragment, + )) + environ["HTTP_DESTINATION"] = rewritten + + return _wsgidav_app(environ, start_response)