game_sync/webapi/api.go

235 lines
5.8 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 webapi
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"github.com/golang-jwt/jwt/v4"
"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
}
func ParseJwtWithClaims(key any, jwtStr string, options ...jwt.ParserOption) (jwt.Claims, error) {
mc := jwt.MapClaims{}
token, err := jwt.ParseWithClaims(jwtStr, mc, func(token *jwt.Token) (interface{}, error) {
return key, nil
}, options...)
if err != nil {
return nil, err
}
// 校验 Claims 对象是否有效,基于 exp过期时间nbf不早于iat签发时间等进行判断如果有这些声明的话
if !token.Valid {
return nil, err
}
return token.Claims, nil
}