diff --git a/request/curl.go b/request/curl.go index 0fb0fc2..bbb913b 100644 --- a/request/curl.go +++ b/request/curl.go @@ -7,6 +7,105 @@ // Date : 2021-08-01 8:47 下午 package request -func Send(apiMethod *APIMethod) { +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "time" + "github.com/tidwall/gjson" + + "github.com/ddliu/go-httpclient" +) + +// Send 发送HTTP请求 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 9:38 下午 2021/8/11 +func Send(apiMethod *APIMethod) *APIResponse { + return nil +} + +// request 发送请求 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2:27 下午 2021/8/12 +func request(method string, fullURL string, parameter map[string]interface{}, header map[string]string, responseConfig *ResponseConfig) (*APIResponse, bool) { + apiResponse := &APIResponse{ + Code: "", + Message: "", + Data: "", + Success: false, + TraceID: "", + Cost: 0, + RealCost: 0, + TotalCost: 0, + TotalRealCost: 0, + ErrorList: make([]error, 0), + StartRequestTime: time.Now().Unix(), + FinishRequestTime: 0, + } + defer func(apiResponse *APIResponse) { + apiResponse.FinishRequestTime = time.Now().Unix() + apiResponse.RealCost = apiResponse.FinishRequestTime - apiResponse.StartRequestTime + }(apiResponse) + if nil == parameter { + parameter = make(map[string]interface{}) + } + if nil == header { + header = make(map[string]string) + } + var ( + client *httpclient.HttpClient + response *httpclient.Response + err error + responseData []byte + ) + client = httpclient.NewHttpClient().WithHeaders(header) + inputByteData, _ := json.Marshal(parameter) + requestData := bytes.NewReader(inputByteData) + if response, err = client.Do(method, fullURL, header, requestData); nil != err { + apiResponse.ErrorList = append(apiResponse.ErrorList, err) + return apiResponse, false + } + if responseData, err = ioutil.ReadAll(response.Body); nil != err { + return apiResponse, false + } + orgData := string(responseData) + apiResponse.Data = gjson.Get(orgData, responseConfig.DataKey).String() + apiResponse.Code = fmt.Sprintf("%v", gjson.Get(orgData, responseConfig.CodeKey).Value()) + apiResponse.Message = gjson.Get(orgData, responseConfig.MessageKey).String() + apiResponse.Cost = gjson.Get(orgData, responseConfig.CostKey).Int() + return apiResponse, false +} + +// isNeedRetry 是否需要重试 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 3:01 下午 2021/8/12 +func isNeedRetry(apiMethod *APIMethod, errType string) bool { + return false +} + +// buildResponseData 构建响应结果 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2:57 下午 2021/8/12 +func buildResponseData(response *httpclient.Response) *APIResponse { + return nil +} + +// buildRequestHeader 构建请求header +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 9:41 下午 2021/8/11 +func buildRequestHeader(apiMethod *APIMethod) map[string]string { + header := make(map[string]string) + return header } diff --git a/request/define.go b/request/define.go index 0493c8d..4af5c94 100644 --- a/request/define.go +++ b/request/define.go @@ -13,12 +13,12 @@ package request // // Date : 8:29 下午 2021/8/1 type APIMethod struct { - ServiceDomain string `json:"service_domain"` // 调用服务的域名 - URI string `json:"uri"` // 调用的URI - Method string `json:"method"` // 请求方法 - ISRestfulURI bool `json:"is_restful_uri"` // 是否为restful uri - Header map[string]string `json:"header"` // 请求header - + ServiceDomain string `json:"service_domain"` // 调用服务的域名 + URI string `json:"uri"` // 调用的URI + Method string `json:"method"` // 请求方法 + ISRestfulURI bool `json:"is_restful_uri"` // 是否为restful uri + Header map[string]string `json:"header"` // 请求header + Parameter map[string]interface{} `json:"parameter"` // 请求参数 } // ResponseConfig ... @@ -27,12 +27,17 @@ type APIMethod struct { // // Date : 8:32 下午 2021/8/1 type ResponseConfig struct { - ISJson bool `json:"is_json"` // 响应数据是否为json - CodeKey string `json:"code_key"` // 代表业务Code的Key - MessageKey string `json:"message_key"` // 描述业务code的key - DataKey string `json:"data_key"` // 返回数据的key - SuccessRule string `json:"success_rule"` // 请求成功的规则, http_code / business_code http状态码或者业务状态码, 如果是通过http code 判断是否为请求成功 code key / message key 配置无效 - SuccessCode []string `json:"success_code"` // 哪些状态码被认为是请求成功 + RetryRule int `json:"retry_rule"` // 重试规则 0 - http error 1 - business error 2 - both 0 && 1 + RetryCnt int `json:"retry_cnt"` // 重试次数(重试次数 1, 最多请求两次) + RetryInterval int `json:"retry_interval"` // 重试的时间间隔, 单位ms, 为 0 立即重试, > 0 休眠指定ms后重试 + ISJson bool `json:"is_json"` // 响应数据是否为json + CodeKey string `json:"code_key"` // 代表业务Code的Key + MessageKey string `json:"message_key"` // 描述业务code的key + TraceKey string `json:"trace_key"` // 接口返回的trace追踪字段key + DataKey string `json:"data_key"` // 返回数据的key + CostKey string `json:"cost_key"` // 代表接口耗时的key + SuccessRule string `json:"success_rule"` // 请求成功的规则, http_code / business_code http状态码或者业务状态码, 如果是通过http code 判断是否为请求成功 code key / message key 配置无效 + SuccessCode []string `json:"success_code"` // 哪些状态码被认为是请求成功 } // APIResponse API响应数据 @@ -41,8 +46,34 @@ type ResponseConfig struct { // // Date : 8:54 下午 2021/8/1 type APIResponse struct { - Data string `json:"data"` // 响应数据 - Cost int64 `json:"cost"` // 接口耗时 - StartRequestTime int64 `json:"start_request_time"` // 开始请求时间 - FinishRequestTime int64 `json:"finish_request_time"` // 完成请求时间 + Code string `json:"code"` // 响应状态码 + Message string `json:"message"` // 响应状态码的描述 + Data string `json:"data"` // 响应数据 + Success bool `json:"success"` // 请求是否成功 + TraceID string `json:"trace_id"` // 日志追踪traceID + Cost int64 `json:"cost"` // 接口耗时(第三方接口返回) + RealCost int64 `json:"real_cost"` // 内部从发起请求,到拿到结果的耗时 + TotalCost int64 `json:"total_cost"` // 累计请求加一起耗时 + TotalRealCost int64 `json:"total_real_cost"` // 累计真实耗时 + ErrorList []error `json:"error_list"` // 重试过程中累计出现过的异常 + StartRequestTime int64 `json:"start_request_time"` // 开始请求时间 + FinishRequestTime int64 `json:"finish_request_time"` // 完成请求时间 } + +const ( + // ResponseErrorTypeInternal 内部异常,请求没发出去 + ResponseErrorTypeInternal = "internal" + // ResponseErrorTypeHttpStatus http 状态码异常 + ResponseErrorTypeHttpStatus = "http" + // ResponseErrorTypeBusinessCode 业务状态码异常 + ResponseErrorTypeBusinessCode = "business" +) + +const ( + // RetryRuleOnlyHttpError 仅 http 异常重试 + RetryRuleOnlyHttpError = 0 + // RetryRuleOnlyBusinessError 仅业务状态码异常重试 + RetryRuleOnlyBusinessError = 1 + // RetryRuleMixed 任意一种异常出现,均重试 + RetryRuleMixed = 2 +)