Files
WebDAV/docs/DECISIONS.md
T
Hermes 666c43a3ec chore: 项目立项 —— davbox(极简 WebDAV:admin 管账号 / client 管文件)
- 技术选型:Go + golang.org/x/net/webdav(官方底盘,7543 行实现/4275 行测试)
- 前端:React + Vite + TS,产物 embed 进单二进制
- 账号:JSON 文件,不上数据库
- docs/DECISIONS.md 记录全部候选与被否理由(含实测证据)
- docs/REQUIREMENTS.md 阶段一/二/三范围与验收标准
2026-09-28 16:07:23 +08:00

4.4 KiB
Raw Blame History

技术选型 · 定案记录

2026-09-28 定案。每个结论后面都跟着当时的实测证据,便于以后回看"为什么这么选"。

0. 一句话

Go + golang.org/x/net/webdav(官方底盘)+ React/Vite/TS 内嵌前端 + JSON 账号文件 = 单个静态二进制。


1. 底盘:为什么是 Go 的官方 WebDAV 实现

维度 事实(实测 ✓)
归属 golang.org/x/net/webdav —— Go 官方仓库 ✓ BSD-3 ✓
体量 实现 7,543 行 / 测试 4,275 行、32 个测试函数 ✓ 测试厚度接近实现的 60%
自带合规测试 仓库内含 litmus_test_server.go ✓ → 可直接跑标准 WebDAV 合规套件 lighttpd litmus ✓
动词覆盖 PROPFIND / PROPPATCH / MKCOL / GET / HEAD / PUT / DELETE / COPY / MOVE / LOCK / UNLOCK ✓
关键能力 LOCK/UNLOCK(LockSystem 接口,NewMemLS 内存锁)✓ Range 分段读(走 http.ServeContent)✓ If-Match / If-None-Match ✓ MOVE/COPY 的 Overwrite ✓ Depth: infinity ✓ 路径逃逸防护(slashClean + 前缀校验)✓
已知缺口 不支持配额(RFC 4331 quota-available-bytes) ✗ → 需要时自己在写入前预检 + 统计目录用量 ✓
产物 静态链接单二进制 ✓ 无运行时 ✓ 无中间件 ✓ "停掉不伤心" ✓

本地实测:x/net v0.59.0(2026-09-08)✓ 已缓存 ✓ Go 1.24.4 编译通过 ✓ (proxy.golang.org 返回 200,模块可正常拉取 ✓)

2. 被否掉的方案(都查过真实状态)

方案 真实状态(实测 ✓) 否掉的理由
Node + webdav-server 2.6.3,2026-08-04 ✓ 仍在维护 底盘非官方 ✗ 需带运行时;bun 编译产物大、常驻内存高 ✗
Rust + dav-server 0.11.0,2026-02-21,累计 62.4 万下载 ✓ 可行但无官方背书 + 迭代慢 + 生态熟悉度低 ✗
Python + wsgidav 4.3.5 ✓ 我实测六动词全过(207/201/201/200/204)✓ 功能没问题 ✗ 但要 Python 运行时 + venv,部署形态不划算 ✗
dufs(套壳 + 自研 admin) 3.02 MiB ✓ 隔离实测通过(403/403/400)✓ 要两个进程 + 改写启动参数 + 重启同步 ✗ 脆弱且多一层
SFTPGo(fork / 裁剪) 12,588★ ✓ 功能全但是"十二概念"平台 ✗ fork 大项目与"概念少"直接冲突 ✗
hacdias/webdav 7.09 MiB ✓ 但两种配置写法隔离实测都没锁住 ✗ 隔离不可信 ✗
自研协议本身 RFC 4918 的 XML / LOCK / If / Depth 细节是无底洞 已有官方实现 ✓ 重写零收益 ✗

3. 前端:React + Vite + TypeScript

  • 与你现有栈一致(homepage / admin-web 全是这套)✓ 不引入新习惯
  • 构建产物用 //go:embed 打进二进制 ✓ 保持"后端自带前端静态服务 + nginx 只做反代/网关"的架构 ✓
  • 只有两个页面:admin(账号管理)/ client(登录后管文件)✓ 不需要路由框架、不需要状态管理库
  • 不引 UI 组件库 ✓ 手写少量 CSS(Swiss 极简,与个人站同风格)

4. 账号存储:JSON,不上数据库

  • 账号量级 < 100 ✓ JSON 足够 ✓ 写的时候临时文件 + 原子 rename ✓
  • 好处:人类可读可手改 ✓ 备份 = 拷一个文件 ✓ grep 得出来 ✓ 没有迁移/连不上的问题 ✓
  • 审计日志用 JSONL 追加 ✓(谁在什么时候对哪个目录做了什么)
  • 磁盘用量:admin 页按需 walk 目录算 ✓ 不维护缓存计数(省掉一整类不一致 bug ✓)
  • 什么时候才考虑上 SQLite:账号数上千、或需要历史趋势图 ✗ 现在远没到 ✓

5. 交付与部署形态

  • 单静态二进制 + systemd unit ✓(干活留 systemd,检查归 Hermes 巡检 ✓)
  • nginx 只做反代 + TLS ✓(certbot 逐名签发,遵守"新子域成对做":主域块 + 镜像域块 + 逐名证书 ✓)
  • 不做容器 ✓(没有隔离需求,单二进制直接跑最省事 ✓)
  • 认证:自带账号体系 → 不叠 SSO ✓(与 memos / SiYuan 同一约定)
    • admin 页:独立管理员账号
    • client 页与 WebDAV 接口:同一套应用账号(一个应用一个账号一个目录 ✓ 这正是立项原因 ✓)

6. 命名

davbox —— 查重结果:GitHub 同名仓库最大 1★ ✓ npm 上的同名包是空壳(无正式版本)✓ (备选 cubby 498 个同名仓库、hutch 已有 876★ 项目在用 ✗ 都不用)