🐛 Bug 修复: - 修复 securecookie: the value is not valid 错误 - 回退密钥处理逻辑确保向后兼容 - 改进会话初始化错误处理 🔧 变更: - 简化 auth.Init 函数 - 密钥不足时仅记录警告 - 更新版本号到 v2.0.1 ✅ 测试确认: - 登录流程正常 - API v1 兼容 - Cookie 向后兼容
197 lines
5.3 KiB
Go
197 lines
5.3 KiB
Go
package main
|
||
|
||
import (
|
||
"flag"
|
||
"fmt"
|
||
"log"
|
||
"net/http"
|
||
"os"
|
||
"os/signal"
|
||
"syscall"
|
||
"time"
|
||
|
||
"sms-receiver-go/auth"
|
||
"sms-receiver-go/config"
|
||
"sms-receiver-go/database"
|
||
"sms-receiver-go/handlers"
|
||
|
||
"github.com/gorilla/mux"
|
||
"github.com/robfig/cron/v3"
|
||
)
|
||
|
||
// 编译时注入的版本信息
|
||
var (
|
||
Version = "dev" // 版本号
|
||
BuildTime = "unknown" // 构建时间
|
||
GitCommit = "unknown" // Git commit hash
|
||
GoVersion = "unknown" // Go 版本
|
||
BuildEnv = "dev" // 构建环境(dev/prod)
|
||
)
|
||
|
||
func printVersion() {
|
||
fmt.Printf("SmsReceiver-go %s\n", Version)
|
||
fmt.Printf(" Version: %s\n", Version)
|
||
fmt.Printf(" Build Env: %s\n", BuildEnv)
|
||
fmt.Printf(" Build Time: %s\n", BuildTime)
|
||
fmt.Printf(" Git Commit: %s\n", GitCommit)
|
||
fmt.Printf(" Go Version: %s\n", GoVersion)
|
||
fmt.Printf(" Repository: https://gitea.king.nyc.mn/openclaw/SmsReceiver-go\n")
|
||
}
|
||
|
||
func main() {
|
||
// 检查是否请求版本信息(需要在 flag.Parse 之前)
|
||
for _, arg := range os.Args[1:] {
|
||
if arg == "--version" || arg == "-v" {
|
||
printVersion()
|
||
os.Exit(0)
|
||
} else if arg == "--help" || arg == "-h" {
|
||
fmt.Println("SmsReceiver-go - 短信转发接收端 Go 版本")
|
||
fmt.Println()
|
||
fmt.Println("Usage:")
|
||
fmt.Println(" sms-receiver-v2 [options]")
|
||
fmt.Println()
|
||
fmt.Println("Options:")
|
||
flag.PrintDefaults()
|
||
fmt.Println()
|
||
fmt.Println("Additional Options:")
|
||
fmt.Println(" -v, --version 显示版本信息")
|
||
fmt.Println(" -h, --help 显示帮助信息")
|
||
os.Exit(0)
|
||
}
|
||
}
|
||
|
||
// 记录启动时间
|
||
startTime := time.Now()
|
||
|
||
// 打印启动信息
|
||
log.Printf("========================================")
|
||
log.Printf("SmsReceiver-go v%s (%s)", Version, BuildEnv)
|
||
log.Printf("========================================")
|
||
log.Printf("Version: %s", Version)
|
||
log.Printf("Build Env: %s", BuildEnv)
|
||
log.Printf("Build Time: %s", BuildTime)
|
||
log.Printf("Git Commit: %s", GitCommit)
|
||
log.Printf("Go Version: %s", GoVersion)
|
||
log.Printf("========================================")
|
||
|
||
// 命令行参数
|
||
configPath := flag.String("config", "config.yaml", "配置文件路径")
|
||
templatesPath := flag.String("templates", "templates", "模板目录路径")
|
||
flag.Parse()
|
||
|
||
// 加载配置
|
||
cfg, err := config.Load(*configPath)
|
||
if err != nil {
|
||
log.Fatalf("加载配置失败: %v", err)
|
||
}
|
||
log.Printf("配置加载成功: %s v%s", cfg.App.Name, cfg.App.Version)
|
||
|
||
// 初始化数据库
|
||
if err := database.Init(&cfg.Database); err != nil {
|
||
log.Fatalf("初始化数据库失败: %v", err)
|
||
}
|
||
defer database.Close()
|
||
|
||
// 初始化会话存储
|
||
auth.Init(cfg.Security.SecretKey)
|
||
|
||
// 验证密钥配置
|
||
if len(cfg.Security.SecretKey) < 16 {
|
||
log.Printf("警告: 安全密钥长度不足,建议至少16字节(当前: %d 字节)", len(cfg.Security.SecretKey))
|
||
}
|
||
|
||
// 初始化模板
|
||
if err := handlers.InitTemplates(*templatesPath); err != nil {
|
||
log.Fatalf("初始化模板失败: %v", err)
|
||
}
|
||
|
||
// 创建路由器
|
||
r := mux.NewRouter()
|
||
|
||
// 静态文件
|
||
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
||
|
||
// 页面路由
|
||
r.HandleFunc("/", handlers.Index)
|
||
r.HandleFunc("/login", handlers.Login)
|
||
r.HandleFunc("/logout", handlers.Logout)
|
||
r.HandleFunc("/message/{id}", handlers.MessageDetail)
|
||
r.HandleFunc("/logs", handlers.Logs)
|
||
r.HandleFunc("/statistics", handlers.Statistics)
|
||
|
||
// API 路由(v1)
|
||
apiV1 := r.PathPrefix("/api/v1").Subrouter()
|
||
apiV1.HandleFunc("/receive", handlers.ReceiveSMS)
|
||
apiV1.HandleFunc("/messages", handlers.APIGetMessages)
|
||
apiV1.HandleFunc("/statistics", handlers.APIStatistics)
|
||
|
||
// 兼容旧版 API(无版本号)
|
||
r.HandleFunc("/api/receive", handlers.ReceiveSMS)
|
||
r.HandleFunc("/api/messages", handlers.APIGetMessages)
|
||
r.HandleFunc("/api/statistics", handlers.APIStatistics)
|
||
|
||
// 健康检查
|
||
r.HandleFunc("/health", handlers.HealthCheck(startTime))
|
||
|
||
// 配置服务器
|
||
server := &http.Server{
|
||
Addr: cfg.GetServerAddress(),
|
||
Handler: r,
|
||
ReadTimeout: 30 * time.Second,
|
||
WriteTimeout: 30 * time.Second,
|
||
IdleTimeout: 60 * time.Second,
|
||
}
|
||
|
||
// 启动后台清理任务
|
||
cronInstance := startCleanupTask(cfg)
|
||
defer cronInstance.Stop()
|
||
|
||
// 优雅关闭
|
||
go func() {
|
||
sigChan := make(chan os.Signal, 1)
|
||
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
||
<-sigChan
|
||
|
||
log.Println("正在关闭服务...")
|
||
server.Close()
|
||
}()
|
||
|
||
log.Printf("服务启动: http://%s", cfg.GetServerAddress())
|
||
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||
log.Fatalf("服务器启动失败: %v", err)
|
||
}
|
||
}
|
||
|
||
// startCleanupTask 启动定期清理任务
|
||
func startCleanupTask(cfg *config.Config) *cron.Cron {
|
||
if !cfg.SMS.AutoCleanup {
|
||
log.Println("自动清理功能未启用")
|
||
return cron.New(cron.WithSeconds())
|
||
}
|
||
|
||
// 创建 cron 实例
|
||
c := cron.New(cron.WithSeconds())
|
||
|
||
// 每天凌晨 3 点执行清理任务
|
||
_, err := c.AddFunc("0 0 3 * * *", func() {
|
||
log.Println("开始执行自动清理任务...")
|
||
deleted, err := database.CleanupOldMessages(cfg.SMS.CleanupDays)
|
||
if err != nil {
|
||
log.Printf("清理旧消息失败: %v", err)
|
||
} else {
|
||
log.Printf("自动清理旧消息完成: 删除 %d 条记录", deleted)
|
||
}
|
||
})
|
||
|
||
if err != nil {
|
||
log.Printf("添加清理任务失败: %v", err)
|
||
return c
|
||
}
|
||
|
||
// 启动 cron 服务
|
||
c.Start()
|
||
log.Println("自动清理任务已启动: 每天 03:00 执行")
|
||
|
||
return c
|
||
}
|