resty_v2 -> resty_v3
This commit is contained in:
13
httpclient/abstract/IRateLimiter.go
Normal file
13
httpclient/abstract/IRateLimiter.go
Normal file
@ -0,0 +1,13 @@
|
||||
// Package abstract ...
|
||||
//
|
||||
// Description : abstract ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2025-05-07 21:13
|
||||
package abstract
|
||||
|
||||
// RateLimiter v2 流控口约束, v3移除了, 人工补齐
|
||||
type RateLimiter interface {
|
||||
Allow() bool
|
||||
}
|
@ -20,7 +20,7 @@ import (
|
||||
"git.zhangdeman.cn/zhangdeman/network/httpclient/log"
|
||||
"git.zhangdeman.cn/zhangdeman/network/httpclient/validate"
|
||||
"git.zhangdeman.cn/zhangdeman/serialize"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"resty.dev/v3"
|
||||
)
|
||||
|
||||
// NewHttpClient 获取http client
|
||||
@ -175,28 +175,6 @@ func (hc *HttpClient) OnRequestFinish(handlerList ...define.RequestFinishHandler
|
||||
hc.requestFinishHandler = append(hc.requestFinishHandler, handlerList...)
|
||||
}
|
||||
|
||||
// getRequestValidateMiddleware 请求验证的Middleware
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 15:40 2024/5/31
|
||||
func (hc *HttpClient) getRequestValidateMiddleware() resty.RequestMiddleware {
|
||||
return func(client *resty.Client, request *resty.Request) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// getResponseValidateMiddleware 获取响应数据验证的middleware
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 15:42 2024/5/31
|
||||
func (hc *HttpClient) getResponseValidateMiddleware() resty.ResponseMiddleware {
|
||||
return func(client *resty.Client, response *resty.Response) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// SetRestyClient 设置client
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
@ -341,8 +319,6 @@ func (hc *HttpClient) Request() *define.Response {
|
||||
//
|
||||
// Date : 18:47 2024/10/9
|
||||
func (hc *HttpClient) requestBackendApi() *define.Response {
|
||||
hc.Client.OnBeforeRequest(hc.getRequestValidateMiddleware()) // 请求参数验证中间件必注册
|
||||
hc.Client.OnAfterResponse(hc.getResponseValidateMiddleware()) // 响应验证中间件必注册
|
||||
var (
|
||||
err error
|
||||
)
|
||||
@ -363,12 +339,20 @@ func (hc *HttpClient) requestBackendApi() *define.Response {
|
||||
response = hc.newResponse()
|
||||
response.Seq = i
|
||||
response.RequestCount = i + 1
|
||||
if nil != hc.reqOption.RateLimiter {
|
||||
if !hc.reqOption.RateLimiter.Allow() {
|
||||
response.FailInfo = &define.ResponseFailInfo{
|
||||
Type: define.RequestFailTypeRateLimit,
|
||||
Message: "rate limit exceeded",
|
||||
}
|
||||
// 命中限流, 忽略重试
|
||||
log.RecordDebug("请求命中限流, 忽略重试策略, 不进行重试", nil, hc.reqCfg)
|
||||
break
|
||||
}
|
||||
}
|
||||
if response.RestyResponse, err = hc.request.Send(); nil != err {
|
||||
errType := define.RequestFailTypeSend
|
||||
if err.Error() == resty.ErrRateLimitExceeded.Error() {
|
||||
// 命中限流
|
||||
errType = define.RequestFailTypeRateLimit
|
||||
} else if netErr, ok := err.(net.Error); ok {
|
||||
if netErr, ok := err.(net.Error); ok {
|
||||
if netErr.Timeout() {
|
||||
// 请求超时
|
||||
errType = define.RequestFailTypeTimeoutError
|
||||
@ -385,11 +369,6 @@ func (hc *HttpClient) requestBackendApi() *define.Response {
|
||||
"err_type": errType,
|
||||
"err_msg": err.Error(),
|
||||
}, hc.reqCfg)
|
||||
if errType == define.RequestFailTypeRateLimit {
|
||||
// 命中限流就不重试了
|
||||
log.RecordDebug("请求命中限流, 忽略重试策略, 不进行重试", nil, hc.reqCfg)
|
||||
break
|
||||
}
|
||||
|
||||
if errType == define.RequestFailTypeTimeoutError && !hc.reqOption.ResponseParser.NeedRetry(hc.reqCfg, response) {
|
||||
// 未配置超时重试
|
||||
|
@ -9,7 +9,6 @@ package define
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
@ -39,7 +38,6 @@ type Request struct {
|
||||
ReadTimeout int64 `json:"read_timeout"` // 读取超时时间
|
||||
RetryRule *RequestRetryRule `json:"retry_rule"` // 重试规则
|
||||
Logger *zap.Logger `json:"-"` // 日志记录器
|
||||
RateLimiter resty.RateLimiter `json:"-"` // 流控实例
|
||||
}
|
||||
|
||||
// RequestRetryRule 重试规则
|
||||
|
@ -8,7 +8,7 @@
|
||||
package define
|
||||
|
||||
import (
|
||||
"github.com/go-resty/resty/v2"
|
||||
"resty.dev/v3"
|
||||
)
|
||||
|
||||
// Response 响应的数据结构定义
|
||||
|
@ -87,7 +87,7 @@ func (r *Response) fillResponseBody(reqCfg *define.Request, response *define.Res
|
||||
jsonByte []byte
|
||||
)
|
||||
|
||||
if err = parser.Unmarshal(response.RestyResponse.Body(), &res); nil != err {
|
||||
if err = parser.Unmarshal(response.RestyResponse.Bytes(), &res); nil != err {
|
||||
return errors.New("response parse body error :" + err.Error())
|
||||
}
|
||||
if jsonByte, err = parser.MarshalForByte(res); nil != err {
|
||||
|
@ -39,6 +39,7 @@ type RequestConfigGroupItem struct {
|
||||
FailBehavior *RequestConfigGroupItemFailBehavior `json:"fail_behavior"` // 失败的行为, 不配置, 默认失败break
|
||||
FinalFailureAllow bool `json:"final_failure_allow"` // 已经确定当前请求是最终失败了,当前请求是否允许执行
|
||||
CacheInstance abstract.ICache `json:"-"` // 数据缓存实例
|
||||
RateLimiter abstract.RateLimiter `json:"-"` // 流控实例
|
||||
ResponseParser abstract.IResponse `json:"-"` // 响应数据解析
|
||||
Condition any `json:"condition"` // TODO: 请求条件, 特定条件下不执行当前请求
|
||||
}
|
||||
|
@ -149,6 +149,7 @@ func (c *client) doRequest(apiList []*RequestConfigGroupItem) bool {
|
||||
apiCfg.RequestCfg.Query = param[strings.ToLower(consts.RequestDataLocationQuery.String())] // query
|
||||
if httpClient, err = httpclient.NewHttpClient(apiCfg.RequestCfg, &httpclient.RequestOption{
|
||||
CacheInstance: apiCfg.CacheInstance,
|
||||
RateLimiter: apiCfg.RateLimiter,
|
||||
ResponseParser: apiCfg.ResponseParser,
|
||||
}); nil != err {
|
||||
// 此处获取客户端实例即发生异常, 忽略一切配置, 直接作为全局失败, 后续也不请求了
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
|
||||
// RequestOption 请求一些选项
|
||||
type RequestOption struct {
|
||||
CacheInstance abstract.ICache `json:"-"` // 数据结果缓存实例
|
||||
ResponseParser abstract.IResponse `json:"-"` // 返回结果解析, 不配置使用内置实现
|
||||
CacheInstance abstract.ICache `json:"-"` // 数据结果缓存实例
|
||||
RateLimiter abstract.RateLimiter `json:"-"` // 流控实例
|
||||
ResponseParser abstract.IResponse `json:"-"` // 返回结果解析, 不配置使用内置实现
|
||||
}
|
||||
|
@ -8,15 +8,14 @@
|
||||
package httpclient
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"git.zhangdeman.cn/zhangdeman/consts"
|
||||
"git.zhangdeman.cn/zhangdeman/network/httpclient/define"
|
||||
"git.zhangdeman.cn/zhangdeman/serialize"
|
||||
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/tidwall/gjson"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"resty.dev/v3"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -31,15 +30,16 @@ func NewRestyClient(reqConfig *define.Request) (*resty.Client, *resty.Request) {
|
||||
if nil == reqConfig {
|
||||
return client, request
|
||||
}
|
||||
if nil != reqConfig.RateLimiter {
|
||||
/*if nil != reqConfig.RateLimiter {
|
||||
// 设置流控实例
|
||||
client.SetRateLimiter(reqConfig.RateLimiter)
|
||||
}
|
||||
}*/
|
||||
formatHeader(reqConfig)
|
||||
client.SetAllowGetMethodPayload(true) // 配置 GET 请求允许带 Body
|
||||
client.SetJSONMarshaler(json.Marshal) // 序列化方法
|
||||
client.SetJSONEscapeHTML(true) // 处理html实体字符
|
||||
client.SetJSONUnmarshaler(serialize.JSON.UnmarshalWithNumber) // 反序列化方法
|
||||
client.SetAllowMethodGetPayload(true) // 配置 GET 请求允许带 Body
|
||||
client.SetAllowMethodDeletePayload(true) // 配置 DELETE 请求允许带 Body
|
||||
client.SetJSONEscapeHTML(true) // 处理html实体字符
|
||||
/*client.SetJSONMarshaler(json.Marshal) // 序列化方法
|
||||
client.SetJSONUnmarshaler(serialize.JSON.UnmarshalWithNumber) // 反序列化方法*/
|
||||
|
||||
request.SetPathParams(reqConfig.PathParam) // 设置path中的参数
|
||||
query := map[string]string{}
|
||||
|
Reference in New Issue
Block a user