184 lines
5.1 KiB
Go
184 lines
5.1 KiB
Go
// Package implement ...
|
|
//
|
|
// Description : implement ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 2025-05-07 14:56
|
|
package implement
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"git.zhangdeman.cn/zhangdeman/consts"
|
|
"git.zhangdeman.cn/zhangdeman/network/httpclient/define"
|
|
"git.zhangdeman.cn/zhangdeman/serialize"
|
|
"github.com/tidwall/gjson"
|
|
"strings"
|
|
)
|
|
|
|
// Response 响应结果解析
|
|
type Response struct {
|
|
}
|
|
|
|
func (r *Response) Parse(reqConfig *define.Request, response *define.Response) error {
|
|
r.fillResponseHeader(response)
|
|
r.fillResponseCookie(response)
|
|
return r.fillResponseBody(reqConfig, response)
|
|
}
|
|
|
|
// fillResponseHeader 填充响应header
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 21:30 2024/6/5
|
|
func (r *Response) fillResponseHeader(response *define.Response) {
|
|
response.Header = map[string]any{} // 清空已有数据
|
|
response.HttpCode = response.RestyResponse.StatusCode() // http状态码
|
|
response.HttpCodeStatus = response.RestyResponse.Status() // http状态码描述
|
|
for headerName, headerValue := range response.RestyResponse.Header() {
|
|
if len(headerValue) > 0 {
|
|
response.Header[headerName] = headerValue[0]
|
|
} else {
|
|
response.Header[headerName] = ""
|
|
}
|
|
}
|
|
}
|
|
|
|
// fillResponseCookie 填充cookie
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 21:32 2024/6/5
|
|
func (r *Response) fillResponseCookie(response *define.Response) {
|
|
response.Cookie = map[string]any{} // 清空已有数据
|
|
for _, cookieValue := range response.RestyResponse.Cookies() {
|
|
response.Cookie[cookieValue.Name] = cookieValue.Value
|
|
}
|
|
}
|
|
|
|
// fillResponseBody 填充响应body
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 21:38 2024/6/5
|
|
func (r *Response) fillResponseBody(reqCfg *define.Request, response *define.Response) error {
|
|
// 解析响应数据类型
|
|
responseContentType := response.RestyResponse.Header().Get(consts.HeaderKeyContentType.String())
|
|
if responseContentType == "" {
|
|
// 返回数据未说明 Content-Type
|
|
return errors.New("response content type is empty")
|
|
}
|
|
typeArr := strings.Split(strings.Split(responseContentType, ";")[0], "/")
|
|
responseType := "json"
|
|
if len(typeArr) > 0 {
|
|
responseType = typeArr[len(typeArr)-1]
|
|
}
|
|
parser := ResponseParserTable[responseType]
|
|
if parser == nil {
|
|
// 未读取到的, 不支持解析对应的响应数据
|
|
return errors.New("response type " + responseType + " is not support")
|
|
|
|
}
|
|
|
|
var (
|
|
err error
|
|
res map[string]any
|
|
jsonByte []byte
|
|
)
|
|
|
|
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 {
|
|
return errors.New("response body Marshal error :" + err.Error())
|
|
}
|
|
response.Data = string(jsonByte)
|
|
response.Code = gjson.Get(response.Data, reqCfg.CodeField).String()
|
|
response.Message = gjson.Get(response.Data, reqCfg.MessageField).String()
|
|
businessData := gjson.Get(response.Data, reqCfg.DataField)
|
|
if businessData.Value() == nil {
|
|
// data为空指针, 归一化成空对象
|
|
response.Body = map[string]any{}
|
|
} else {
|
|
if businessData.IsArray() {
|
|
// 数组类型的转换
|
|
response.Data = fmt.Sprintf(`{"list":` + businessData.String() + "}")
|
|
} else {
|
|
if businessData.IsObject() {
|
|
// 返回的就是对象
|
|
response.Data = businessData.String()
|
|
} else {
|
|
// 返回是普通类型
|
|
response.Data = serialize.JSON.MarshalForStringIgnoreError(map[string]any{
|
|
"value": businessData.Value(),
|
|
})
|
|
}
|
|
}
|
|
_ = serialize.JSON.UnmarshalWithNumber([]byte(response.Data), &response.Body)
|
|
}
|
|
|
|
response.ExtendData = map[string]string{}
|
|
gjson.Parse(response.Data).ForEach(func(key, value gjson.Result) bool {
|
|
if key.String() == reqCfg.CodeField ||
|
|
key.String() == reqCfg.MessageField ||
|
|
key.String() == reqCfg.DataField {
|
|
return true
|
|
}
|
|
response.ExtendData[key.String()] = value.String()
|
|
return true
|
|
})
|
|
return nil
|
|
}
|
|
|
|
// BusinessSuccess ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 22:48 2024/6/6
|
|
func (r *Response) BusinessSuccess(reqCfg *define.Request, response *define.Response) bool {
|
|
for _, itemSuccessCode := range reqCfg.SuccessCodeList {
|
|
if itemSuccessCode == response.Code {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// HttpSuccess ...
|
|
func (r *Response) HttpSuccess(reqCfg *define.Request, response *define.Response) bool {
|
|
if len(reqCfg.SuccessHttpCodeList) == 0 {
|
|
// 没配置, 则 2xx 均视为成功
|
|
return response.HttpCode/100 == 2
|
|
}
|
|
for _, itemHttpCode := range reqCfg.SuccessHttpCodeList {
|
|
if itemHttpCode == response.HttpCode {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// NeedRetry 是否需要重试
|
|
func (r *Response) NeedRetry(reqCfg *define.Request, response *define.Response) bool {
|
|
if nil == reqCfg.RetryRule {
|
|
// 未配置重试规则
|
|
return false
|
|
}
|
|
if reqCfg.RetryRule.RetryCount <= 0 {
|
|
// 未配置重试次数
|
|
return false
|
|
}
|
|
for _, httpCode := range reqCfg.RetryRule.RetryHttpCodeList {
|
|
if response.HttpCode == int(httpCode) {
|
|
return true
|
|
}
|
|
}
|
|
for _, businessCode := range reqCfg.RetryRule.RetryBusinessCodeList {
|
|
if businessCode == response.Code {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|