package webapi import ( "bytes" "crypto/tls" "encoding/json" "fmt" "io" "net" "net/http" "net/url" "strings" "sync" "sync/atomic" "time" "google.golang.org/protobuf/proto" "mongo.games.com/goserver/core/logger" ) const DEFAULT_TIMEOUT = time.Second * 30 var WebApiStats = new(sync.Map) type ApiStats struct { RunTimes int64 //执行次数 TotalRuningTime int64 //总执行时间 MaxRuningTime int64 //最长执行时间 TimeoutTimes int64 //执行超时次数 } func DeviceOs(os string) string { switch os { case "ios": return "2" case "android": return "1" default: return "0" } } // API调用 // action 为需要调用的api, 例如 /api/Send/SendCode // params 为需发送的参数 // protocol = https || http ||Post func API_OP(url string, params url.Values) (map[string]interface{}, error) { //res, err := http.PostForm("http://192.168.1.160:9090/api/Sms/SendCaptcha", params) res, err := http.PostForm(Config.GameApiURL+url, params) if err != nil { return nil, err } defer res.Body.Close() body, err := io.ReadAll(res.Body) if err != nil { return nil, err } //println(url, " ret:", string(body[:])) result := make(map[string]interface{}) json.Unmarshal(body, &result) return result, nil } // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // GET方式请求 func getRequest(appId, action string, params map[string]string, body proto.Message, protocol string, dura time.Duration) ([]byte, error) { var client *http.Client if strings.ToUpper(protocol) == "HTTPS" { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client = &http.Client{Transport: tr} } else { client = &http.Client{} } data, err := proto.Marshal(body) if err != nil { return nil, err } callUrl := MakeURL(appId, action, params, data) logger.Logger.Tracef("getRequest url: %v params: %v request body: %v", callUrl, params, body) req, err := http.NewRequest("GET", callUrl, nil) if err != nil { return nil, err } var stats *ApiStats if v, exist := WebApiStats.Load(action); exist { stats = v.(*ApiStats) } else { stats = &ApiStats{} WebApiStats.Store(action, stats) } var isTimeout bool start := time.Now() defer func() { ps := int64(time.Now().Sub(start) / time.Millisecond) if stats != nil { if isTimeout { atomic.AddInt64(&stats.TimeoutTimes, 1) } atomic.AddInt64(&stats.RunTimes, 1) atomic.AddInt64(&stats.TotalRuningTime, ps) if atomic.LoadInt64(&stats.MaxRuningTime) < ps { atomic.StoreInt64(&stats.MaxRuningTime, ps) } } }() //设置超时 client.Timeout = dura req.Close = true resp, err := client.Do(req) if err != nil { if uerr, ok := err.(net.Error); ok { isTimeout = uerr.Timeout() } return nil, err } defer resp.Body.Close() if resp.StatusCode == 200 { body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } return body, err } logger.Logger.Errorf("getRequest url:%v params:%v request body:%v code:%v", callUrl, params, body, resp.StatusCode) return nil, fmt.Errorf("StatusCode:%d", resp.StatusCode) } // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // POST方式请求 func postRequest(appId, action string, params map[string]string, body proto.Message, protocol string, dura time.Duration) ([]byte, error) { var client *http.Client if strings.ToUpper(protocol) == "HTTPS" { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client = &http.Client{Transport: tr} } else { client = &http.Client{} } data, err := proto.Marshal(body) if err != nil { return nil, err } callUrl := MakeURL(appId, action, params, data) logger.Logger.Tracef("postRequest url: %v request body: %v", callUrl, body) req, err := http.NewRequest("POST", callUrl, bytes.NewBuffer(data)) if err != nil { return nil, err } var stats *ApiStats if v, exist := WebApiStats.Load(action); exist { stats = v.(*ApiStats) } else { stats = &ApiStats{} WebApiStats.Store(action, stats) } var isTimeout bool start := time.Now() defer func() { ps := int64(time.Now().Sub(start) / time.Millisecond) if stats != nil { if isTimeout { atomic.AddInt64(&stats.TimeoutTimes, 1) } atomic.AddInt64(&stats.RunTimes, 1) atomic.AddInt64(&stats.TotalRuningTime, ps) if atomic.LoadInt64(&stats.MaxRuningTime) < ps { atomic.StoreInt64(&stats.MaxRuningTime, ps) } } }() //设置超时 client.Timeout = dura req.Close = true resp, err := client.Do(req) if err != nil { if uerr, ok := err.(net.Error); ok { isTimeout = uerr.Timeout() } return nil, err } defer resp.Body.Close() if resp.StatusCode == http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } return body, err } logger.Logger.Errorf("postRequest url:%v request body: %v code: %v", callUrl, body, resp.StatusCode) return nil, fmt.Errorf("StatusCode:%d", resp.StatusCode) } func Stats() map[string]ApiStats { stats := make(map[string]ApiStats) WebApiStats.Range(func(k, v interface{}) bool { if s, ok := v.(*ApiStats); ok { ss := *s //计数可能不精准 stats[k.(string)] = ss } return true }) return stats }