feat: 补齐第一批已知缺口(关闭握手 / 定时备份 / Origin 白名单 / DTO 收敛)
- httpapi:新增 POST /api/shutdown(admin 会话或 X-Shutdown-Token 常量时间比对) 与 GET /api/rules/switches(recorder 可读,只回布尔开关);settings/standings 的 重复 DTO 收敛到 internal/dto;standings.showIndividualMedals 贯通到设置读写与前端 - export:抽出 export.Service,新增自动备份定时任务(backup.intervalMinutes/keep), 自动、手动、发布前三类备份共用同一把互斥锁与滚动清理 - realtime:/ws 去掉 InsecureSkipVerify,改用 OriginPatterns(同源与无 Origin 放行, 跨站需命中 server.allowedOrigins) - console:停止服务改走 POST /api/shutdown 优雅关闭(5 秒宽限后回退强杀), 服务管理器新增「已连接的大屏实例」卡片 - deploy:build.bat 改用 for /f 读内部署名——set /p 在 chcp 65001 下返回空, 导致最近这次构建的 exe 里根本没注入署名 - docs:备份策略、关闭超时、Origin 配置的说明与实现对齐
This commit is contained in:
1 parent
4d56c73ae6
commit
2c9ff65fc4
42 files changed
+1271
-275
No files matched your search
+17
-7
@@ -85,6 +85,7 @@ func main() {
|
||||
|
||||
authSvc := auth.New(st.DB(), auth.Options{Logger: logger})
|
||||
hub := realtime.NewHub(eventDB, logger)
|
||||
hub.SetAllowedOrigins(cfg.Server.AllowedOrigins)
|
||||
defer func() { _ = hub.Close() }()
|
||||
|
||||
// 可信代理:默认空,表示不采信任何代理头(见 devdocs/08 第 1 节)。
|
||||
@@ -110,15 +111,20 @@ func main() {
|
||||
logger.Warn("已创建默认管理员", "username", username, "password", password)
|
||||
}
|
||||
|
||||
backupSvc := export.NewService(st.DB(), eventDB, filepath.Join(cfg.DataDir, "backups"), cfg.Backup.Keep, logger)
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: cfg.Server.Addr(),
|
||||
Handler: httpapi.New(httpapi.Options{
|
||||
Logger: logger,
|
||||
Version: version,
|
||||
System: st.DB(),
|
||||
Event: eventDB,
|
||||
Auth: authSvc,
|
||||
DataDir: cfg.DataDir,
|
||||
Logger: logger,
|
||||
Version: version,
|
||||
System: st.DB(),
|
||||
Event: eventDB,
|
||||
Auth: authSvc,
|
||||
DataDir: cfg.DataDir,
|
||||
Backup: backupSvc,
|
||||
// POST /api/shutdown 复用同一个关闭信号:取消 ctx 后走下面的 Shutdown + 关库。
|
||||
Shutdown: stop,
|
||||
ProjectDir: filepath.Join(cfg.DataDir, "event_projs", *project),
|
||||
Display: displaySender{hub: hub},
|
||||
Realtime: hub,
|
||||
@@ -127,6 +133,9 @@ func main() {
|
||||
ReadHeaderTimeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
// 定时备份跟随服务端生命周期:收到退出信号(ctx 取消)即停止。
|
||||
backupSvc.StartAuto(ctx, time.Duration(cfg.Backup.IntervalMinutes)*time.Minute)
|
||||
|
||||
go func() {
|
||||
logger.Info("服务启动", "addr", srv.Addr, "version", version)
|
||||
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
@@ -138,7 +147,8 @@ func main() {
|
||||
<-ctx.Done()
|
||||
|
||||
logger.Info("正在关闭…")
|
||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
// Console 的关闭握手要求 3 秒内完成,超时后仍会关库并退出(defer 顺序保证)。
|
||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
if err := srv.Shutdown(shutdownCtx); err != nil {
|
||||
logger.Error("关闭超时", "err", err)
|
||||
|
||||
Reference in new issue
Block a user