66 lines
4.3 KiB
Markdown
66 lines
4.3 KiB
Markdown
# 技术选型 · 定案记录
|
||
|
||
> 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
|
||
|
||
- 生态成熟、构建产物小、长期可维护 ✓
|
||
- 构建产物用 `//go:embed` 打进二进制 ✓ 保持"**后端自带前端静态服务 + nginx 只做反代/网关**"的架构 ✓
|
||
- 只有两个页面:**admin**(账号管理)/ **client**(登录后管文件)✓ 不需要路由框架、不需要状态管理库
|
||
- 不引 UI 组件库 ✓ 手写少量 CSS(Swiss 极简)
|
||
|
||
## 4. 账号存储:JSON,不上数据库
|
||
|
||
- 账号量级 < 100 ✓ JSON 足够 ✓ 写的时候临时文件 + 原子 rename ✓
|
||
- 好处:**人类可读可手改** ✓ 备份 = 拷一个文件 ✓ grep 得出来 ✓ 没有迁移/连不上的问题 ✓
|
||
- 审计日志用 JSONL 追加 ✓(谁在什么时候对哪个目录做了什么)
|
||
- 磁盘用量:admin 页按需 `walk` 目录算 ✓ 不维护缓存计数(省掉一整类不一致 bug ✓)
|
||
- 什么时候才考虑上 SQLite:账号数上千、或需要历史趋势图 ✗ 现在远没到 ✓
|
||
|
||
## 5. 交付与部署形态
|
||
|
||
- **单静态二进制** + systemd unit ✓
|
||
- nginx 只做反代 + TLS ✓(证书交给 certbot)
|
||
- **不做容器** ✓(没有隔离需求,单二进制直接跑最省事 ✓)
|
||
- 认证:**自带账号体系且开箱即用** ✓;管理端可关闭自带口令(`AUTH_MODE=sso`),协议端点永远保留自带账号 ✓
|
||
- admin 页:独立管理员账号
|
||
- client 页与 WebDAV 接口:**同一套应用账号**(一个应用一个账号一个目录 ✓ 这正是立项原因 ✓)
|
||
|
||
## 6. 命名
|
||
|
||
`davbox` —— 查重结果:GitHub 同名仓库最大 1★ ✓ npm 上的同名包是空壳(无正式版本)✓
|
||
(备选 `cubby` 498 个同名仓库、`hutch` 已有 876★ 项目在用 ✗ 都不用)
|