diff --git a/app/services/userCenterService/auth.go b/app/services/userCenterService/auth.go index 9db2e05..d85aa47 100644 --- a/app/services/userCenterService/auth.go +++ b/app/services/userCenterService/auth.go @@ -16,10 +16,11 @@ func Login(stuId string, pass string) error { } loginUrl.RawQuery = params.Encode() urlPath := loginUrl.String() - regMap := make(map[string]any) - regMap["stu_id"] = stuId - regMap["password"] = pass - regMap["bound_system"] = 1 + regMap := map[string]any{ + "stu_id": stuId, + "password": pass, + "bound_system": 1, + } resp, err := FetchHandleOfPost(regMap, userCenterApi.UserCenterApi(urlPath)) if err != nil { return apiException.RequestError diff --git a/app/services/userCenterService/fetch.go b/app/services/userCenterService/fetch.go index 8b94f5a..9899d72 100644 --- a/app/services/userCenterService/fetch.go +++ b/app/services/userCenterService/fetch.go @@ -1,10 +1,8 @@ package userCenterService import ( - "encoding/json" - "4u-go/app/apiException" - "4u-go/app/utils/fetch" + "4u-go/app/utils/request" "4u-go/config/api/userCenterApi" ) @@ -15,18 +13,23 @@ type UserCenterResponse struct { Data any `json:"data"` } -// FetchHandleOfPost 向用户中心发送post请求 +// FetchHandleOfPost 向用户中心发送 POST 请求 func FetchHandleOfPost(form map[string]any, url userCenterApi.UserCenterApi) (*UserCenterResponse, error) { - f := fetch.Fetch{} - f.Init() - res, err := f.PostJsonForm(userCenterApi.UserCenterHost+string(url), form) - if err != nil { - return nil, apiException.RequestError - } - rc := UserCenterResponse{} - err = json.Unmarshal(res, &rc) - if err != nil { + client := request.New() + var rc UserCenterResponse + + // 发送 POST 请求并自动解析 JSON 响应 + resp, err := client.Request(). + SetHeader("Content-Type", "application/json"). + SetBody(form). + SetResult(&rc). + Post(userCenterApi.UserCenterHost + string(url)) + + // 检查请求错误 + if err != nil || resp.IsError() { return nil, apiException.RequestError } + + // 返回解析后的响应 return &rc, nil } diff --git a/app/services/userCenterService/reg.go b/app/services/userCenterService/reg.go index a810e7f..70508dd 100644 --- a/app/services/userCenterService/reg.go +++ b/app/services/userCenterService/reg.go @@ -16,13 +16,14 @@ func RegWithoutVerify(stuId string, pass string, iid string, email string, userT } userUrl.RawQuery = params.Encode() urlPath := userUrl.String() - regMap := make(map[string]any) - regMap["stu_id"] = stuId - regMap["password"] = pass - regMap["iid"] = iid - regMap["email"] = email - regMap["type"] = userType - regMap["bound_system"] = 1 + regMap := map[string]any{ + "stu_id": stuId, + "password": pass, + "iid": iid, + "email": email, + "type": userType, + "bound_system": 1, + } resp, err := FetchHandleOfPost(regMap, userCenterApi.UserCenterApi(urlPath)) if err != nil { return err diff --git a/app/utils/fetch/fetch.go b/app/utils/fetch/fetch.go deleted file mode 100644 index cb6bf0e..0000000 --- a/app/utils/fetch/fetch.go +++ /dev/null @@ -1,130 +0,0 @@ -//nolint:all -package fetch - -import ( - "bytes" - "crypto/tls" - "encoding/json" - "io" - "net/http" - "net/url" - "strings" - "time" -) - -// Fetch HTTP 客户端 -type Fetch struct { - Cookie []*http.Cookie - client *http.Client -} - -// InitUnSafe 初始化一个 HTTP 客户端,该客户端跳过 TLS 证书验证 (不安全) -func (f *Fetch) InitUnSafe() { - f.client = &http.Client{ - CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }, - Timeout: time.Second * 15, - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - }, - } -} - -// Init 初始化一个安全的 HTTP 客户端,不跳过 TLS 验证 -func (f *Fetch) Init() { - f.client = &http.Client{ - CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }, - Timeout: time.Second * 15, - } -} - -// SkipTlsCheck 动态设置客户端跳过 TLS 证书验证 -func (f *Fetch) SkipTlsCheck() { - f.client.Transport = &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - } -} - -// Get 发起一个 GET 请求,并返回响应的内容 -func (f *Fetch) Get(url string) ([]byte, error) { - response, err := f.GetRaw(url) - if err != nil { - return nil, err - } - s, err := io.ReadAll(response.Body) - if err != nil { - return nil, err - } - return s, nil -} - -// GetRaw 发起一个 GET 请求,返回原始 HTTP 响应对象 -func (f *Fetch) GetRaw(url string) (*http.Response, error) { - request, err := http.NewRequest("GET", url, nil) - if err != nil { - return nil, err - } - for _, v := range f.Cookie { - request.AddCookie(v) - } - response, err := f.client.Do(request) - if err != nil { - return nil, err - } - f.Cookie = cookieMerge(f.Cookie, response.Cookies()) - return response, err -} - -// PostFormRaw 发起一个 POST 表单请求,返回原始 HTTP 响应 -func (f *Fetch) PostFormRaw(url string, requestData url.Values) (*http.Response, error) { - request, _ := http.NewRequest("POST", url, strings.NewReader(requestData.Encode())) - request.Header.Set("Content-Type", "application/x-www-form-urlencoded") - for _, v := range f.Cookie { - request.AddCookie(v) - } - return f.client.Do(request) -} - -// PostForm 发起一个 POST 表单请求,并返回响应的内容 -func (f *Fetch) PostForm(url string, requestData url.Values) ([]byte, error) { - response, err := f.PostFormRaw(url, requestData) - if err != nil { - return nil, err - } - f.Cookie = cookieMerge(f.Cookie, response.Cookies()) - return io.ReadAll(response.Body) -} - -// PostJsonFormRaw 发起一个 POST JSON 请求,返回原始 HTTP 响应对象 -func (f *Fetch) PostJsonFormRaw(url string, requestData map[string]any) (*http.Response, error) { - bytesData, _ := json.Marshal(requestData) - request, _ := http.NewRequest("POST", url, bytes.NewReader(bytesData)) - request.Header.Set("Content-Type", "application/json") - for _, v := range f.Cookie { - request.AddCookie(v) - } - return f.client.Do(request) -} - -// PostJsonForm 发起一个 POST JSON 请求,并返回响应的内容 -func (f *Fetch) PostJsonForm(url string, requestData map[string]any) ([]byte, error) { - response, err := f.PostJsonFormRaw(url, requestData) - if err != nil { - return nil, err - } - f.Cookie = cookieMerge(f.Cookie, response.Cookies()) - return io.ReadAll(response.Body) -} - -// cookieMerge 合并新的 Cookie,将已有的同名 Cookie 替换 -func cookieMerge(cookieA []*http.Cookie, cookieB []*http.Cookie) []*http.Cookie { - for _, v := range cookieB { - for k, v2 := range cookieA { - if v.Name == v2.Name { - cookieA = append(cookieA[:k], cookieA[k+1:]...) - break - } - } - } - cookieA = append(cookieA, cookieB...) - return cookieA -} diff --git a/app/utils/request/request.go b/app/utils/request/request.go new file mode 100644 index 0000000..0e490d6 --- /dev/null +++ b/app/utils/request/request.go @@ -0,0 +1,54 @@ +//nolint:all +package request + +import ( + "crypto/tls" + "time" + + "github.com/go-resty/resty/v2" + "go.uber.org/zap" +) + +// Client 包装 Resty 客户端 +type Client struct { + *resty.Client +} + +// New 初始化一个 Resty 客户端 +func New() Client { + s := Client{ + Client: resty.New(). + SetTimeout(10 * time.Second). + SetRetryCount(3). + SetRetryWaitTime(2 * time.Second), + } + // 利用中间件实现请求日志 + s.OnAfterResponse(RestyLogMiddleware) + return s +} + +// NewUnSafe 初始化一个 Resty 客户端并跳过 TLS 证书验证 +func NewUnSafe() Client { + s := New() + s.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) + return s +} + +// Request 获取一个新的请求实例 +func (s Client) Request() *resty.Request { + return s.R().EnableTrace() +} + +// RestyLogMiddleware Resty日志中间件 +func RestyLogMiddleware(_ *resty.Client, resp *resty.Response) error { + if resp.IsError() { + method := resp.Request.Method + url := resp.Request.URL + zap.L().Warn("请求出现错误", + zap.String("method", method), + zap.String("url", url), + zap.Float64("time_spent", resp.Time().Seconds()), + ) + } + return nil +} diff --git a/go.mod b/go.mod index c2aceae..e27bb76 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/gin-contrib/sessions v1.0.1 github.com/gin-gonic/gin v1.10.0 github.com/go-redis/redis/v8 v8.11.5 + github.com/go-resty/resty/v2 v2.16.0 github.com/silenceper/wechat/v2 v2.1.7 github.com/spf13/viper v1.19.0 go.uber.org/zap v1.27.0 @@ -32,7 +33,7 @@ require ( github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.22.1 // indirect + github.com/go-playground/validator/v10 v10.23.0 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/goccy/go-json v0.10.3 // indirect github.com/gomodule/redigo v2.0.0+incompatible // indirect diff --git a/go.sum b/go.sum index eea0465..7f96125 100644 --- a/go.sum +++ b/go.sum @@ -54,10 +54,12 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= -github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o= +github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-resty/resty/v2 v2.16.0 h1:qpKalHWI2bpp9BIKlyT8TYWEJXOk1NuKbfiT3RRnzWc= +github.com/go-resty/resty/v2 v2.16.0/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= @@ -254,6 +256,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=