package main import ( "database/sql" "errors" "fmt" "github.com/gin-gonic/gin" _ "github.com/mattn/go-sqlite3" "log" "net/http" "time" ) // MappingInfo 用于存储映射信息 type MappingInfo struct { RuleName string `json:"rule_name"` IpAddr string `json:"ip_addr"` Ip string `json:"ip"` Port string `json:"port"` LastUpdate time.Time `json:"last_update"` } // 全局变量,存储所有映射信息 var mappings = make(map[string]*MappingInfo) var db *sql.DB var dbFileName = "./mappings.db" // 数据库文件名 var tableName = "mappings" // 数据库表名 var query = `SELECT name FROM sqlite_master WHERE type='table' AND name=?;` // 查询表是否存在的SQL语句 var createTableSQL = `CREATE TABLE IF NOT EXISTS ` + tableName + ` ( "RuleName" TEXT PRIMARY KEY, "IPAddress" TEXT, "Ip" TEXT, "Port" TEXT, "LastUpdate" TEXT );` // 创建表的SQL语句 func main() { InitDB() // 初始化数据库 defer func(db *sql.DB) { err := db.Close() if err != nil { log.Fatal(err) } }(db) router := gin.Default() // 处理Webhook的路由 router.POST("/webhook", func(c *gin.Context) { var info MappingInfo if err := c.BindJSON(&info); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } info.LastUpdate = time.Now() // 输出一下info fmt.Println(info) mappings[info.RuleName] = &info updateMapping(info) // 更新数据库中的映射信息 c.JSON(http.StatusOK, gin.H{"status": "updated"}) }) // 提供Web服务的路由,展示映射信息 router.GET("/mappings", func(c *gin.Context) { c.JSON(http.StatusOK, mappings) }) // 根据RuleName查询映射信息 router.GET("/mappings/:RuleName", func(c *gin.Context) { serviceName := c.Param("RuleName") if info, exists := mappings[serviceName]; exists { c.JSON(http.StatusOK, info) } else { c.JSON(http.StatusNotFound, gin.H{"code": http.StatusNotFound, "error": "service not found"}) } }) // 根据RuleName跳转到映射的服务 router.GET("/:RuleName", func(c *gin.Context) { serviceName := c.Param("RuleName") if info, exists := mappings[serviceName]; exists { url := "http://" + info.Ip + ":" + info.Port c.Redirect(http.StatusMovedPermanently, url) } else { c.JSON(http.StatusNotFound, gin.H{"code": http.StatusNotFound, "error": "service not found"}) } }) // 启动定时任务,检查映射信息更新 go checkMappings() err := router.Run(":8080") if err != nil { return } // 在8080端口启动服务 } // 定时检查映射信息是否需要更新 func checkMappings() { for { time.Sleep(24 * time.Hour) // 每天检查一次 for _, info := range mappings { if time.Since(info.LastUpdate) > 24*time.Hour { // 如果超过一天没有更新,则主动查询API(这里需要实现API查询逻辑) } } } } func InitDB() { log.Println("Init DB...") var err error db, err = sql.Open("sqlite3", dbFileName) if err != nil { log.Fatal(err) } err = db.QueryRow(query, tableName).Scan(&tableName) if errors.Is(err, sql.ErrNoRows) { log.Println("Table not exists, create it...") createTable() } else if err != nil { log.Fatal(err) } else { // 读取数据库中的映射信息 mappings = readMappings() fmt.Println(mappings) } log.Println("Init DB done.") } // 创建映射表 func createTable() { _, err := db.Exec(createTableSQL) if err != nil { log.Fatal(err) } } // 从数据库读取映射信息 func readMappings() map[string]*MappingInfo { mappings := make(map[string]*MappingInfo) rows, err := db.Query("SELECT RuleName, IPAddress, Ip, Port, LastUpdate FROM mappings") if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { var info MappingInfo var lastUpdate string err = rows.Scan(&info.RuleName, &info.IpAddr, &info.Ip, &info.Port, &lastUpdate) if err != nil { log.Fatal(err) } info.LastUpdate, err = time.Parse(time.RFC3339, lastUpdate) if err != nil { log.Fatal(err) } mappings[info.RuleName] = &info } return mappings } // 更新数据库中的映射信息 func updateMapping(info MappingInfo) { _, err := db.Exec("INSERT OR REPLACE INTO mappings (RuleName, IPAddress, Ip, Port, LastUpdate) VALUES (?, ?, ?, ?, ?)", info.RuleName, info.IpAddr, info.Ip, info.Port, info.LastUpdate.Format(time.RFC3339)) if err != nil { log.Fatal(err) } }