package middleware import ( "net" "net/http" "strings" "github.com/gin-gonic/gin" "github.com/oschwald/geoip2-golang" ) func GeoRedirect(mapping map[string]string, defaultHost string) gin.HandlerFunc { db, err := geoip2.Open("./GeoLite2-Country/GeoLite2-Country.mmdb") if err != nil { // 如果打开失败,返回不执行重定向的中间件 return func(c *gin.Context) { c.Next() } } return func(c *gin.Context) { defer c.Next() // 获取真实客户端 IP(考虑代理) ipStr := c.Request.Header.Get("X-Forwarded-For") if ipStr == "" { ipStr = c.ClientIP() } else { // X-Forwarded-For 可能是逗号分隔的列表,取第一个 ipStr = strings.TrimSpace(strings.Split(ipStr, ",")[0]) } ip := net.ParseIP(ipStr) if ip == nil { return } record, err := db.Country(ip) if err != nil { return } iso := record.Country.IsoCode // 如 "US", "CN", "BR" target, ok := mapping[iso] if !ok { target = defaultHost } // 如果目标域名与当前请求不同,重定向(保留路径/查询) if target != "" && !strings.Contains(c.Request.Host, target) { location := "https://" + target + c.Request.URL.RequestURI() // 302 临时重定向;如需永久改用 http.StatusMovedPermanently c.Redirect(http.StatusFound, location) c.Abort() return } } }