package utils import ( "strings" "github.com/gin-gonic/gin" ) // ClientIP 获取客户端真实IP func ClientIP(c *gin.Context) string { // 优先取反向代理头 for _, header := range []string{"X-Real-IP", "X-Forwarded-For"} { if v := c.GetHeader(header); v != "" { ips := strings.Split(v, ",") ip := strings.TrimSpace(ips[0]) if ip != "" { return ip } } } return c.ClientIP() } // SanitizePath 清理虚拟路径,防止路径穿越 func SanitizePath(p string) string { p = strings.ReplaceAll(p, "\\", "/") parts := make([]string, 0, 8) for _, seg := range strings.Split(p, "/") { seg = strings.TrimSpace(seg) if seg == "" || seg == "." { continue } if seg == ".." { if len(parts) > 0 { parts = parts[:len(parts)-1] } continue } parts = append(parts, seg) } return strings.Join(parts, "/") } // IsValidPassword 检查密码强度:至少8位,包含字母和数字 func IsValidPassword(pwd string) bool { if len(pwd) < 8 { return false } hasLetter, hasDigit := false, false for _, ch := range pwd { switch { case ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z': hasLetter = true case ch >= '0' && ch <= '9': hasDigit = true } } return hasLetter && hasDigit } // IsEmail 简单校验邮箱格式 func IsEmail(s string) bool { at := strings.IndexByte(s, '@') if at <= 0 || at == len(s)-1 { return false } domain := s[at+1:] return strings.Contains(domain, ".") && strings.IndexByte(domain, '.') != 0 && strings.IndexByte(domain, '.') != len(domain)-1 } // HumanSize 将字节数转为可读大小 func HumanSize(n int64) string { const unit = 1024 if n < unit { return itoa(n) + " B" } div, exp := int64(unit), 0 for m := n / unit; m >= unit && exp < 4; m /= unit { div *= unit exp++ } val := float64(n) / float64(div) s := trimFloat(val) units := []string{"KB", "MB", "GB", "TB", "PB"} return s + " " + units[exp] } func itoa(n int64) string { if n == 0 { return "0" } neg := n < 0 if neg { n = -n } var buf [20]byte i := len(buf) for n > 0 { i-- buf[i] = byte('0' + n%10) n /= 10 } if neg { i-- buf[i] = '-' } return string(buf[i:]) } func trimFloat(f float64) string { // 保留两位小数并去掉末尾多余的0 s := itoa(int64(f)) frac := f - float64(int64(f)) if frac < 0.005 { return s } d1 := int64(frac * 10) if d1 > 9 { d1 = 9 } frac = frac*10 - float64(d1) d2 := int64(frac * 10) if d2 > 9 { d2 = 9 } if d2 < 5 { if d1 == 0 { return s } return s + "." + itoa(d1) } return s + "." + itoa(d1) + itoa(d2) }