WebDAV 服务调试方法论
触发条件
WebDAV 同步失败、502/405 等非预期错误、客户端报错但服务端日志不明。
参考文件
references/nginx-webdav-proxy.md— OpenList WebDAV 完整 Nginx 代理配置模板(含 Lua Destination 重写)
环境提示
- 用户 fish shell 不支持 bash heredoc(
<< 'EOF'),编辑容器内文件用docker cp+python3 -c或sed - Docker 容器重启会丢
/etc/hosts,host.docker.internal不可靠,直接用172.17.0.1
调试流程
1. 分层隔离——最核心原则
不要在猜疑链里打转。每层独立验证:
- 客户端层:curl 直接模拟客户端行为(相同 URL、相同 header)
- 代理层(容器内):
docker exec <container> curl http://localhost:<port>/...— 绕过外部网络 - 上游服务层:直接 curl 上游地址(如
http://172.17.0.1:5244),完全绕过代理
案例:本次 debug 花了数小时怀疑 WAF,但容器内 MOVE 是 200 外部却是 502——说明问题在 WAF 和上游之间那层。最终发现是 OpenList 拒绝了 Destination 绝对 URL。
2. 不要假定上游支持标准协议
- WebDAV RFC 规定 Destination 可以是绝对 URL,但 OpenList 只接受相对路径
- 操作:遇到协议级错误(如 502),先测试变体(相对路径 vs 绝对路径、不同 header 值)
3. 502 ≠ 代理连不上上游
502 的常见原因不止"上游宕机":
- 上游接受了连接但返回了无效响应(nginx 判定为 bad gateway)
- 上游对特定 HTTP 方法或 header 组合静默断开
- WAF/Lua 模块在代理层静默拦截
关键教训:error.log 没日志 ≠ 没问题。本次 error.log 对 MOVE 完全没有错误记录,但 502 确实在发生。
4. 权限/文件类型问题
GET /dav/head.json→ 405,因为磁盘上head.json是目录而非文件- 删除时注意:DELETE 请求可能被 WAF/登录页拦截,用
rm -rf直接从磁盘删除更可靠 - PROPFIND 返回
<D:collection/>就是目录——客户端 GET 目录会 405
5. Docker 容器注意事项
host.docker.internal依赖/etc/hosts,容器重启/重建后会丢失- 直接用 Docker 网桥 IP(
172.17.0.1),这个不会变 - 在宿主机上改容器内文件:
docker cp拉出 → 修改 →docker cp塞回
6. WAF 烟雾弹识别
- 1Panel WAF 的
siteConfig.json有 methodWhite/header/xss 等规则 - 全部关掉问题依旧 → WAF 不是根因,不要再浪费时间
nginx -s reload不刷新 Lua 共享内存,需要docker restart完全重启- 修改容器内文件注意持久化:容器重启后
/etc/hosts等会丢失