github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/netx/local.go (about) 1 package netx 2 3 import ( 4 "fmt" 5 "net/http" 6 "time" 7 8 "github.com/bingoohuang/gg/pkg/goip" 9 "github.com/bingoohuang/gg/pkg/netx/freeport" 10 "github.com/bingoohuang/gg/pkg/ss" 11 "github.com/bingoohuang/golog/pkg/randx" 12 "github.com/go-resty/resty/v2" 13 ) 14 15 // IsLocalAddr 判断addr(ip,域名等)是否指向本机 16 // 由于IP可能经由 iptable 指向,或者可能是域名,或者其它,不能直接与本机IP做对比 17 // 本方法构建一个临时的HTTP服务,然后使用指定的addr去连接改HTTP服务,如果能连接上,说明addr是指向本机的地址 18 func IsLocalAddr(addr string) (bool, error) { 19 if addr == "localhost" || addr == "127.0.0.1" || addr == "::1" { 20 return true, nil 21 } 22 23 if ss.AnyOf(addr, goip.ListIfaceNames()...) { 24 return true, nil 25 } 26 27 port, err := freeport.PortE() 28 if err != nil { 29 return false, err 30 } 31 32 radStr := randx.String(512) 33 mux := http.NewServeMux() 34 mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { 35 _, _ = fmt.Fprint(w, radStr) 36 }) 37 38 server := &http.Server{Addr: fmt.Sprintf(":%d", port), Handler: mux} 39 40 go func() { _ = server.ListenAndServe() }() 41 42 time.Sleep(100 * time.Millisecond) // nolint gomnd 43 44 addr = `http://` + JoinHostPort(addr, port) 45 resp, err := resty.New().SetTimeout(3 * time.Second).R().Get(addr) 46 _ = server.Close() 47 48 if err != nil { 49 return false, err 50 } 51 52 return resp.String() == radStr, nil 53 } 54 55 // JoinHostPort make IP:Port for ipv4/domain or [IPv6]:Port for ipv6. 56 func JoinHostPort(host string, port int) string { 57 if goip.IsIPv6(host) { 58 return fmt.Sprintf("[%s]:%d", host, port) 59 } 60 61 return fmt.Sprintf("%s:%d", host, port) 62 }