package app import ( "encoding/json" "fmt" "io" "log/slog" "net" "net/http" g "proxy-server/gateway/globals" "strings" ) const base = "https://whois.pconline.com.cn/ipJson.jsp?json=true&ip=" func IpGeo(ip net.IP) (info *IpGeoInfo, err error) { defer func() { var rs = recover() if reErr, ok := rs.(error); ok { err = fmt.Errorf("执行归属地查询异常 %w", reErr) } }() // 本地归属地查询 str, err := g.Geo.SearchByStr(ip.String()) if err != nil { return nil, err } if str != "" { slog.Debug("本地解析归属地结果", "str", str) values := strings.Split(str, "|") if len(values) != 5 { return nil, fmt.Errorf("本地归属地查询解析失败") } return &IpGeoInfo{ Prov: values[2], City: values[3], Isp: values[4], }, nil } // 归属地查询 var url = base + ip.String() resp, err := http.Get(url) if err != nil { return nil, fmt.Errorf("查询归属地失败: %w", err) } if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("查询归属地失败: %s", resp.Status) } defer func(Body io.ReadCloser) { _ = Body.Close() }(resp.Body) // 返回节点信息 var bytes []byte _, err = io.ReadFull(resp.Body, bytes) if err != nil { return nil, fmt.Errorf("读取归属地响应失败: %w", err) } var body = make(map[string]any) err = json.Unmarshal(bytes, &body) if err != nil { return nil, fmt.Errorf("解析归属地响应失败: %w", err) } return &IpGeoInfo{ Prov: body["pro"].(string), City: body["city"].(string), Isp: strings.Split(body["addr"].(string), " ")[1], }, nil } type IpGeoInfo struct { Prov string City string Isp string }