github.com/songzhibin97/gkit@v1.2.13/net/ip/ip.go (about) 1 package ip 2 3 import ( 4 "errors" 5 "math" 6 "net" 7 "net/http" 8 "strings" 9 ) 10 11 const ( 12 xForwardedFor = "X-Forwarded-For" 13 xRealIP = "X-Real-IP" 14 ) 15 16 func HasLocalIPAddr(ip string) bool { 17 return HasLocalIP(net.ParseIP(ip)) 18 } 19 20 func HasLocalIP(ip net.IP) bool { 21 if ip.IsLoopback() { 22 return true 23 } 24 25 ip4 := ip.To4() 26 if ip4 == nil { 27 return false 28 } 29 30 return ip4[0] == 10 || // 10.0.0.0/8 31 (ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31) || // 172.16.0.0/12 32 (ip4[0] == 169 && ip4[1] == 254) || // 169.254.0.0/16 33 (ip4[0] == 192 && ip4[1] == 168) // 192.168.0.0/16 34 } 35 36 func ClientIP(req *http.Request) string { 37 if ip := strings.TrimSpace(strings.Split(req.Header.Get(xForwardedFor), ",")[0]); ip != "" { 38 return ip 39 } 40 if ip := strings.TrimSpace(req.Header.Get(xRealIP)); ip != "" { 41 return ip 42 } 43 return RemoteIP(req) 44 } 45 46 func ClientPublicIP(req *http.Request) string { 47 if ip := strings.TrimSpace(strings.Split(req.Header.Get(xForwardedFor), ",")[0]); ip != "" && !HasLocalIPAddr(ip) { 48 return ip 49 } 50 if ip := strings.TrimSpace(req.Header.Get(xRealIP)); ip != "" && !HasLocalIPAddr(ip) { 51 return ip 52 } 53 if ip := RemoteIP(req); ip != "" && !HasLocalIPAddr(ip) { 54 return ip 55 } 56 return "" 57 } 58 59 func RemoteIP(req *http.Request) string { 60 ip, _, err := net.SplitHostPort(strings.TrimSpace(req.RemoteAddr)) 61 if err != nil { 62 return "" 63 } 64 return ip 65 } 66 67 func IsWebsocket(req *http.Request) bool { 68 if strings.Contains(strings.ToLower(requestHeader(req, "Connection")), "upgrade") && 69 strings.EqualFold(requestHeader(req, "Upgrade"), "websocket") { 70 return true 71 } 72 return false 73 } 74 75 func requestHeader(req *http.Request, key string) string { 76 return req.Header.Get(key) 77 } 78 79 // ContentType returns the Content-Type header of the request. 80 func ContentType(req *http.Request) string { 81 return filterFlags(requestHeader(req, "Content-Type")) 82 } 83 84 func filterFlags(content string) string { 85 for i, char := range content { 86 if char == ' ' || char == ';' { 87 return content[:i] 88 } 89 } 90 return content 91 } 92 93 func StringToLong(ip string) (uint, error) { 94 b := net.ParseIP(ip).To4() 95 if b == nil { 96 return 0, errors.New("invalid ipv4 format") 97 } 98 99 return uint(b[3]) | uint(b[2])<<8 | uint(b[1])<<16 | uint(b[0])<<24, nil 100 } 101 102 func LongToIPString(i uint) (string, error) { 103 if i > math.MaxUint32 { 104 return "", errors.New("beyond the scope of ipv4") 105 } 106 107 ip := make(net.IP, net.IPv4len) 108 ip[0] = byte(i >> 24) 109 ip[1] = byte(i >> 16) 110 ip[2] = byte(i >> 8) 111 ip[3] = byte(i) 112 113 return ip.String(), nil 114 } 115 116 func ToLong(ip net.IP) (uint, error) { 117 b := ip.To4() 118 if b == nil { 119 return 0, errors.New("invalid ipv4 format") 120 } 121 122 return uint(b[3]) | uint(b[2])<<8 | uint(b[1])<<16 | uint(b[0])<<24, nil 123 } 124 125 func LongToIP(i uint) (net.IP, error) { 126 if i > math.MaxUint32 { 127 return nil, errors.New("beyond the scope of ipv4") 128 } 129 130 ip := make(net.IP, net.IPv4len) 131 ip[0] = byte(i >> 24) 132 ip[1] = byte(i >> 16) 133 ip[2] = byte(i >> 8) 134 ip[3] = byte(i) 135 136 return ip, nil 137 }