package api import ( "net" "net/http" "strings" ) type ServerInfo struct { Port int `json:"port"` Host string `json:"host"` LocalIPs []string `json:"local_ips"` SuggestedURL string `json:"suggested_url"` DashboardURL string `json:"dashboard_url"` WebSocketURL string `json:"websocket_url"` } func GetServerInfo(w http.ResponseWriter, r *http.Request, publicURLOverride string) { host := r.Host if idx := strings.Index(host, ":"); idx > 0 { host = host[:idx] } localIPs := listLocalIPv4() suggestedHost := host if isLoopbackHost(host) && len(localIPs) > 0 { suggestedHost = localIPs[0] } port := 8989 if idx := strings.LastIndex(r.Host, ":"); idx > 0 { if p := r.Host[idx+1:]; p != "" { port = parsePort(p) } } suggestedURL := "http://" + net.JoinHostPort(suggestedHost, itoa(port)) if strings.TrimSpace(publicURLOverride) != "" { suggestedURL = strings.TrimSpace(publicURLOverride) } info := ServerInfo{ Port: port, Host: host, LocalIPs: localIPs, SuggestedURL: suggestedURL, DashboardURL: suggestedURL, WebSocketURL: strings.Replace(strings.Replace(suggestedURL, "https://", "wss://", 1), "http://", "ws://", 1) + "/ws/agent", } writeJSON(w, info) } func listLocalIPv4() []string { var ips []string ifaces, err := net.Interfaces() if err != nil { return ips } for _, iface := range ifaces { if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 { continue } addrs, err := iface.Addrs() if err != nil { continue } for _, addr := range addrs { var ip net.IP switch v := addr.(type) { case *net.IPNet: ip = v.IP case *net.IPAddr: ip = v.IP } if ip == nil || ip.IsLoopback() { continue } ip = ip.To4() if ip == nil { continue } ips = append(ips, ip.String()) } } return ips } func isLoopbackHost(host string) bool { return host == "localhost" || host == "127.0.0.1" || host == "::1" } func parsePort(s string) int { n := 0 for _, ch := range s { if ch < '0' || ch > '9' { return 8989 } n = n*10 + int(ch-'0') } if n == 0 { return 8989 } return n } func itoa(n int) string { if n == 0 { return "0" } var buf [16]byte i := len(buf) for n > 0 { i-- buf[i] = byte('0' + n%10) n /= 10 } return string(buf[i:]) }