Files

66 lines
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 技术选型 · 定案记录
> 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★ 项目在用 ✗ 都不用)