修复方案:在 routes/webdav.py 中添加了一个 WSGI 中间件包装函数,在请求到达 WsgiDAV 前:
1. 读取 X-Forwarded-Proto 设置正确的 wsgi.url_scheme 2. 将 Destination 头中的外部 scheme/host 重写为内部实际值
This commit is contained in:
parent
5d97be9557
commit
38c5d1e622
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user