Chat stays usable when the file service is off or down. Files up to 256 MB are hosted like chat; downloads try the host first and fall back to file-service tickets. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> [CI]
WebDrop 服务端
.NET 10,NativeAOT。设计见 ../docs,接口契约见 ../docs/openapi.yaml。
结构
| 项目 | 职责 |
|---|---|
src/WebDrop.Core |
领域类型、规则和业务逻辑(ChannelService、ShareService),不做 IO,只依赖抽象 |
src/WebDrop.Storage |
SQLite 存储(SqliteChannelStore)和磁盘 blob(DiskBlobStore) |
src/WebDrop.Frontend |
可选嵌入 Vite dist,提供静态文件、SPA fallback 与页面 CSP;不依赖业务层 |
src/WebDrop.Api |
Minimal API、WebSocket / SSE / 长轮询、订阅枢纽、后台清理、限流、安全头 |
tests/ |
Core.Tests(单元与服务层,真实 SQLite)、Api.Tests(真实 Kestrel 上的集成测试) |
常用命令
dotnet test # 全部测试
dotnet run --project src/WebDrop.Api # 开发运行,默认 http://localhost:5000
npm --prefix ../web run build # 先构建前端时,dotnet publish 会自动嵌入 web/dist
# NativeAOT 发布(Windows 需要 vswhere.exe 在 PATH 里)
$env:PATH += ";${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer"
dotnet publish src/WebDrop.Api -c Release -r win-x64 -o out/win-x64
pwsh scripts/smoke.ps1 -Exe out/win-x64/webdrop.exe # 对原生产物做端到端冒烟(含 WebSocket)
python3 scripts/smoke.py out/linux-x64/webdrop # 跨平台版本,只用标准库,不含 WebSocket
配置
配置节 WebDrop,环境变量写法 WebDrop__DataDir、WebDrop__Captcha__Provider。完整默认值见 src/WebDrop.Api/appsettings.json。
| 键 | 默认 | 说明 |
|---|---|---|
DataDir |
data |
SQLite 数据库和 blob 目录 |
CorsOrigins |
空 | 前端所在的源;前端托管在独立域名,必须列出,否则不发 CORS 头 |
TrustForwardedHeaders |
false | 在反向代理之后开启,限流按真实 IP 分区 |
EnableHttp3 |
false | 仅在 /info 里通告,服务进程不内置 QUIC |
RequestsPerMinute / ChannelCreatesPerMinute |
600 / 30 | 按 IP 的限流,只在内存里 |
ShareDraftTtlSeconds |
86400 | 未完成分享草稿的保留时间 |
Captcha:Provider |
none |
创建频道的验证码:none 或 cap。选 cap 时下面三项必填,缺失会在启动时报错 |
Captcha:ApiEndpoint |
空 | 浏览器里 Cap widget 连接的地址,形如 https://cap.example.com/<site_key>/,经 /info 下发 |
Captcha:SiteverifyUrl |
空 | 本服务调用 Cap 校验 token 的地址,形如 https://cap.example.com/<site_key>/siteverify,可以是内网地址 |
Captcha:Secret |
空 | Cap 站点密钥的 secret,只在服务端使用 |
Limits:* |
见 ServerLimits |
负载、帧数、频道字节数、成员人数上限、TTL 上限等 |
约束
- 单实例部署:订阅枢纽在进程内,多实例需要换成外部发布订阅。
- 日志不记录请求头、请求体、完整 URL;Hosting 诊断日志已关闭,避免频道 id 进入日志。
- NativeAOT:不用 SignalR、EF Core、MVC、反射式 JSON;所有 AOT / 裁剪警告视为错误。
WebDrop.Frontend只负责嵌入静态资源与 SPA fallback。Containerfile自动构建web/;单独发布 API 时,只有web/dist存在或指定WebDropFrontendDist后才包含前端。
验证码(Cap)
工作量证明不由本项目实现,交给 Cap。默认 Provider=none,适合开发和小型自托管。需要防刷时:
- 部署 Cap Standalone(官方是 Docker 容器,依赖 Redis/Valkey),建一个站点密钥。
- 配置
Captcha:Provider=cap、ApiEndpoint、SiteverifyUrl、Secret。 - 前端读取
/info的captcha.api_endpoint,用 Cap widget 求解后把 token 放进X-WD-Cap创建频道。
测试状态:服务端对 Cap 的调用只用一个假 Cap 服务(按其文档的 POST /<site_key>/siteverify、{secret, response} → {success} 实现)测过,尚未与真实的 Cap 联调。部署前请用真实实例跑一遍创建流程。Cap 不可用时创建频道会返回 503 captcha_unavailable(fail closed),不会放行。