ssgf_utils/ip_tool/hua_chen_client.go
2025-06-17 17:05:22 +08:00

147 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package ip_tool
import (
"context"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
"time"
"github.com/pkg/errors"
)
type HuaChenIpClient struct {
AppCode string
Host string
cache ICacheAdapter
}
func NewHuaChenIpClient(appCode string, cache ICacheAdapter) *HuaChenIpClient {
return &HuaChenIpClient{
AppCode: appCode,
Host: "https://c2ba.api.huachen.cn",
cache: cache,
}
}
func (h *HuaChenIpClient) GetIpInfo(ip string) (res *ApiResult, err error) {
if ip == "" {
return nil, errors.New("请输入ip地址")
}
// 设置参数
params := url.Values{}
params.Add("ip", ip)
// 拼接URL
var fullURL string
fullURL, err = url.JoinPath(h.Host, "ip")
if err != nil {
return nil, errors.Wrapf(err, "获取ip:%s信息失败拼接路径错误", ip)
}
// 拼接参数
fullURL = fmt.Sprintf("%s?%s", fullURL, params.Encode())
// 创建HTTP客户端
client := &http.Client{}
// 创建请求
var req *http.Request
req, err = http.NewRequest(http.MethodGet, fullURL, nil)
if err != nil {
return nil, errors.Wrapf(err, "获取ip:%s信息失败创建请求失败", ip)
}
// 设置请求头
req.Header.Add("Authorization", "APPCODE "+h.AppCode)
req.Header.Add("Content-Type", "application/json")
// 发送请求
client.Timeout = 5 * time.Second
var resp *http.Response
resp, err = client.Do(req)
if err != nil {
return nil, errors.Wrapf(err, "获取ip:%s信息失败发送请求失败", ip)
}
defer func(Body io.ReadCloser) {
err = Body.Close()
if err != nil {
log.Printf("获取ip:%s信息关闭响应体失败: %+v\n", ip, err)
}
}(resp.Body)
// 读取响应体
var body []byte
body, err = io.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrapf(err, "获取ip:%s信息失败读取响应体失败", ip)
}
// 解析JSON响应
var apiResult ApiResult
err = json.Unmarshal(body, &apiResult)
if err != nil {
return nil, errors.Wrapf(err, "获取ip:%s信息失败解析JSON响应失败%s", ip, string(body))
}
// 检查API返回状态
if apiResult.Ret != 200 {
return &apiResult, errors.New(fmt.Sprintf("获取ip:%s信息失败%+v", ip, apiResult))
}
return &apiResult, nil
}
func (h *HuaChenIpClient) GetIpInfoFormCache(ctx context.Context, ip string, ttl time.Duration) (res *ApiResult, err error) {
getCache, err := h.cache.Get(ctx, h.ipKey(ip))
if err != nil {
return nil, errors.Wrapf(err, "获取缓存失败ip:%s", ip)
}
if getCache != nil {
return getCache, nil
}
res, err = h.GetIpInfo(ip)
if err != nil {
return nil, errors.Wrapf(err, "获取ip:%s信息失败", ip)
}
var infoJson []byte
infoJson, err = json.Marshal(res)
if err != nil {
return nil, errors.Wrapf(err, "无法将IP信息转换为JSONip:%s", ip)
}
err = h.cache.Set(ctx, h.ipKey(ip), string(infoJson), ttl)
if err != nil {
return nil, errors.Wrapf(err, "缓存ip:%s信息失败", ip)
}
return
}
// ipKey 生成Redis key
func (h *HuaChenIpClient) ipKey(ip string) string {
return fmt.Sprintf("ip:%s", ip)
}
type ApiResult struct {
Ret int `json:"ret"`
Msg string `json:"msg"`
Data IpInfo `json:"data"`
LogId string `json:"log_id"`
}
type IpInfo struct {
Ip string `json:"ip"`
LongIp string `json:"long_ip"`
Isp string `json:"isp"`
Area string `json:"area"`
RegionId string `json:"region_id"`
Region string `json:"region"`
CityId string `json:"city_id"`
City string `json:"city"`
District string `json:"district"`
DistrictId string `json:"district_id"`
CountryId string `json:"country_id"`
Country string `json:"country"`
Lat string `json:"lat"`
Lng string `json:"lng"`
}