- fk. Request.Close = true for weixin api.

This commit is contained in:
gazebo
2018-08-16 11:03:06 +08:00
parent 47e1b3989d
commit fa6ac348e3
8 changed files with 210 additions and 196 deletions

View File

@@ -99,27 +99,32 @@ func (a *API) AccessAPI(apiStr string, params map[string]interface{}) (retVal Re
params2 := utils.MergeMaps(utils.Params2Map("key", a.key, "output", "json"), params) params2 := utils.MergeMaps(utils.Params2Map("key", a.key, "output", "json"), params)
params2[signKey] = a.signParams(params2) params2[signKey] = a.signParams(params2)
// request, _ := http.NewRequest(http.MethodGet, utils.GenerateGetURL(prodURL, apiStr, params2), nil) err = platformapi.AccessPlatformAPIWithRetry(a.client,
err = platformapi.AccessPlatformAPIWithRetry(a.client, http.MethodGet, utils.GenerateGetURL(prodURL, apiStr, params2), "", nil, a.config, func(response *http.Response) (errLevel string, err error) { func() *http.Request {
jsonResult1, err := utils.HTTPResponse2Json(response) request, _ := http.NewRequest(http.MethodGet, utils.GenerateGetURL(prodURL, apiStr, params2), nil)
if err != nil { return request
return platformapi.ErrLevelGeneralFail, platformapi.ErrResponseDataFormatWrong },
} a.config,
status := jsonResult1["status"].(string) func(response *http.Response) (errLevel string, err error) {
if status == StatusCodeSuccess { jsonResult1, err := utils.HTTPResponse2Json(response)
retVal = jsonResult1 if err != nil {
return platformapi.ErrLevelSuccess, nil return platformapi.ErrLevelGeneralFail, platformapi.ErrResponseDataFormatWrong
} }
infoCode := jsonResult1["infocode"].(string) status := jsonResult1["status"].(string)
newErr := utils.NewErrorCode(jsonResult1["info"].(string), infoCode) if status == StatusCodeSuccess {
if _, ok := exceedLimitCodes[infoCode]; ok { retVal = jsonResult1
return platformapi.ErrLevelExceedLimit, newErr return platformapi.ErrLevelSuccess, nil
} else if _, ok := canRetryCodes[infoCode]; ok { }
return platformapi.ErrLevelRecoverableErr, newErr infoCode := jsonResult1["infocode"].(string)
} else { newErr := utils.NewErrorCode(jsonResult1["info"].(string), infoCode)
return platformapi.ErrLevelCodeIsNotOK, newErr if _, ok := exceedLimitCodes[infoCode]; ok {
} return platformapi.ErrLevelExceedLimit, newErr
}) } else if _, ok := canRetryCodes[infoCode]; ok {
return platformapi.ErrLevelRecoverableErr, newErr
} else {
return platformapi.ErrLevelCodeIsNotOK, newErr
}
})
return retVal, err return retVal, err
} }

View File

@@ -1,6 +1,7 @@
package dadaapi package dadaapi
import ( import (
"bytes"
"crypto/md5" "crypto/md5"
"fmt" "fmt"
"net/http" "net/http"
@@ -107,32 +108,36 @@ func (a *API) AccessAPI(action string, params map[string]interface{}) (retVal *R
} }
params2[signKey] = a.signParams(params2) params2[signKey] = a.signParams(params2)
params2Bytes := utils.MustMarshal(params2) params2Bytes := utils.MustMarshal(params2)
// request, _ := http.NewRequest(http.MethodPost, a.url+"/"+action, bytes.NewReader(params2Bytes))
header := make(http.Header)
header.Set("Content-Type", "application/json")
err = platformapi.AccessPlatformAPIWithRetry(a.client, http.MethodPost, a.url+"/"+action, string(params2Bytes), header, a.config, func(response *http.Response) (result string, err error) { err = platformapi.AccessPlatformAPIWithRetry(a.client,
jsonResult1, err := utils.HTTPResponse2Json(response) func() *http.Request {
if err != nil { request, _ := http.NewRequest(http.MethodPost, a.url+"/"+action, bytes.NewReader(params2Bytes))
return platformapi.ErrLevelGeneralFail, err request.Header.Set("Content-Type", "application/json")
} return request
code := int(utils.MustInterface2Int64(jsonResult1["code"])) },
retVal = &ResponseResult{ a.config,
Code: code, func(response *http.Response) (result string, err error) {
ErrorCode: code, jsonResult1, err := utils.HTTPResponse2Json(response)
Msg: jsonResult1["msg"].(string), if err != nil {
Status: jsonResult1["status"].(string), return platformapi.ErrLevelGeneralFail, err
} }
if code == ResponseCodeSuccess { code := int(utils.MustInterface2Int64(jsonResult1["code"]))
retVal.Result = jsonResult1["result"] retVal = &ResponseResult{
return platformapi.ErrLevelSuccess, nil Code: code,
} ErrorCode: code,
newErr := utils.NewErrorIntCode(retVal.Msg, code) Msg: jsonResult1["msg"].(string),
if code == ResponseCodeRetryLater || code == ResponseCodeNetworkErr { Status: jsonResult1["status"].(string),
return platformapi.ErrLevelRecoverableErr, newErr }
} if code == ResponseCodeSuccess {
return platformapi.ErrLevelCodeIsNotOK, newErr retVal.Result = jsonResult1["result"]
}) return platformapi.ErrLevelSuccess, nil
}
newErr := utils.NewErrorIntCode(retVal.Msg, code)
if code == ResponseCodeRetryLater || code == ResponseCodeNetworkErr {
return platformapi.ErrLevelRecoverableErr, newErr
}
return platformapi.ErrLevelCodeIsNotOK, newErr
})
return retVal, err return retVal, err
} }

View File

@@ -1,6 +1,7 @@
package elmapi package elmapi
import ( import (
"bytes"
"crypto/md5" "crypto/md5"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
@@ -145,38 +146,42 @@ func (a *API) AccessAPI(action string, params map[string]interface{}) (retVal *R
} }
pl.Signature = a.signParams(action, pl) pl.Signature = a.signParams(action, pl)
plBytes := utils.MustMarshal(pl)
bodyStr := string(utils.MustMarshal(pl)) err = platformapi.AccessPlatformAPIWithRetry(a.client,
// request, _ := http.NewRequest(http.MethodPost, a.fullURL, strings.NewReader(bodyStr)) func() *http.Request {
header := make(http.Header) request, _ := http.NewRequest(http.MethodPost, a.fullURL, bytes.NewReader(plBytes))
header.Set("Content-Type", "application/json; charset=utf-8") request.Header.Set("Content-Type", "application/json; charset=utf-8")
header.Set("Content-Encoding", "gzip, deflate") request.Header.Set("Content-Encoding", "gzip, deflate")
header.Set("User-Agent", "eleme-golang-api") request.Header.Set("User-Agent", "eleme-golang-api")
err = platformapi.AccessPlatformAPIWithRetry(a.client, http.MethodPost, a.fullURL, bodyStr, header, a.config, func(response *http.Response) (result string, err error) { return request
jsonResult1, err := utils.HTTPResponse2Json(response) },
if err != nil { a.config,
return platformapi.ErrLevelGeneralFail, err func(response *http.Response) (result string, err error) {
} jsonResult1, err := utils.HTTPResponse2Json(response)
resultError, _ := jsonResult1["error"].(map[string]interface{}) if err != nil {
retVal = &ResponseResult{ return platformapi.ErrLevelGeneralFail, err
ID: jsonResult1["id"].(string), }
Error: resultError, resultError, _ := jsonResult1["error"].(map[string]interface{})
Result: jsonResult1["result"], retVal = &ResponseResult{
} ID: jsonResult1["id"].(string),
errinfoMap := retVal.Error Error: resultError,
if errinfoMap == nil { Result: jsonResult1["result"],
return platformapi.ErrLevelSuccess, nil }
} errinfoMap := retVal.Error
code := errinfoMap["code"].(string) if errinfoMap == nil {
newErr := utils.NewErrorCode(errinfoMap["message"].(string), code) return platformapi.ErrLevelSuccess, nil
if code == "EXCEED_LIMIT" { }
return platformapi.ErrLevelExceedLimit, newErr code := errinfoMap["code"].(string)
} else if code == "SERVER_ERROR" || code == "BIZ_SYSTEM_ERROR" || code == "BIZ_1006" || code == "BUSINESS_ERROR" { newErr := utils.NewErrorCode(errinfoMap["message"].(string), code)
return platformapi.ErrLevelRecoverableErr, newErr if code == "EXCEED_LIMIT" {
} else { return platformapi.ErrLevelExceedLimit, newErr
return platformapi.ErrLevelCodeIsNotOK, newErr } else if code == "SERVER_ERROR" || code == "BIZ_SYSTEM_ERROR" || code == "BIZ_1006" || code == "BUSINESS_ERROR" {
} return platformapi.ErrLevelRecoverableErr, newErr
}) } else {
return platformapi.ErrLevelCodeIsNotOK, newErr
}
})
return retVal, err return retVal, err
} }
@@ -195,37 +200,31 @@ func (a *API) getAuthorizeURL() string {
} }
func (a *API) AcccessAPI2(baseURL string, params map[string]interface{}, method string) (retVal map[string]interface{}, err error) { func (a *API) AcccessAPI2(baseURL string, params map[string]interface{}, method string) (retVal map[string]interface{}, err error) {
// var request *http.Request err = platformapi.AccessPlatformAPIWithRetry(a.client,
body := "" func() *http.Request {
requestURL := baseURL var request *http.Request
var header http.Header if method == http.MethodPost {
if method == http.MethodPost { params2 := make(url.Values)
params2 := make(url.Values) for k, v := range params {
for k, v := range params { params2[k] = []string{fmt.Sprint(v)}
params2[k] = []string{fmt.Sprint(v)} }
} request, _ = http.NewRequest(method, baseURL, strings.NewReader(params2.Encode()))
body = params2.Encode() request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
// request, _ = http.NewRequest(http.MethodPost, baseURL, strings.NewReader(params2.Encode())) request.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(a.appKey+":"+a.secret)))
header = make(http.Header) } else {
header.Set("Content-Type", "application/x-www-form-urlencoded") request, _ = http.NewRequest(method, utils.GenerateGetURL(baseURL, "", params), nil)
header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(a.appKey+":"+a.secret))) }
} else { return request
requestURL = utils.GenerateGetURL(baseURL, "", params) },
// fullURL, _ := url.Parse(utils.GenerateGetURL(baseURL, "", params)) a.config,
// // baseapi.SugarLogger.Debug(url.String()) func(response *http.Response) (result string, err error) {
// request = &http.Request{ jsonResult1, err := utils.HTTPResponse2Json(response)
// Method: http.MethodGet, if err != nil {
// URL: fullURL, return platformapi.ErrLevelGeneralFail, err
// } }
} retVal = jsonResult1
err = platformapi.AccessPlatformAPIWithRetry(a.client, method, requestURL, body, header, a.config, func(response *http.Response) (result string, err error) { return platformapi.ErrLevelSuccess, nil
jsonResult1, err := utils.HTTPResponse2Json(response) })
if err != nil {
return platformapi.ErrLevelGeneralFail, err
}
retVal = jsonResult1
return platformapi.ErrLevelSuccess, nil
})
return retVal, err return retVal, err
} }

View File

@@ -23,7 +23,7 @@ func init() {
// sandbox // sandbox
elmapi = New("623c0904c0d2499e83df15b62902eb65", "RwT214gAsS", "56afff4b9ebd8a7eb532d18fa33f17be57f9b9db", false) elmapi = New("623c0904c0d2499e83df15b62902eb65", "RwT214gAsS", "56afff4b9ebd8a7eb532d18fa33f17be57f9b9db", false)
// prod // prod
// elmapi = New("b0168650ad84a44e49d7613e88d31572", "KLRDcOZGrk", "1fc221f8265506531da36fb613d5f5ad673f2e9a", true) // elmapi = New("fee89f45d06f93037dd314ceb78fde7b", "KLRDcOZGrk", "1fc221f8265506531da36fb613d5f5ad673f2e9a", true)
} }
func TestTest(t *testing.T) { func TestTest(t *testing.T) {

View File

@@ -143,27 +143,33 @@ func (a *API) AccessAPI(apiStr string, jdParams map[string]interface{}) (retVal
params["timestamp"] = utils.GetCurTimeStr() params["timestamp"] = utils.GetCurTimeStr()
sign := a.signParams(params) sign := a.signParams(params)
params[signKey] = sign params[signKey] = sign
// request, _ := http.NewRequest(http.MethodGet, utils.GenerateGetURL(prodURL, apiStr, params), nil)
//request.Close = true //todo 为了性能考虑 err = platformapi.AccessPlatformAPIWithRetry(a.client,
err = platformapi.AccessPlatformAPIWithRetry(a.client, http.MethodGet, utils.GenerateGetURL(prodURL, apiStr, params), "", nil, a.config, func(response *http.Response) (errLevel string, err error) { func() *http.Request {
jsonResult1, err := utils.HTTPResponse2Json(response) request, _ := http.NewRequest(http.MethodGet, utils.GenerateGetURL(prodURL, apiStr, params), nil)
if err != nil { // request.Close = true //todo 为了性能考虑还是不要关闭
return platformapi.ErrLevelGeneralFail, platformapi.ErrResponseDataFormatWrong return request
} },
code := jsonResult1["code"].(string) a.config,
if code == ResponseCodeSuccess { func(response *http.Response) (errLevel string, err error) {
retVal = jsonResult1 jsonResult1, err := utils.HTTPResponse2Json(response)
return platformapi.ErrLevelSuccess, nil if err != nil {
} return platformapi.ErrLevelGeneralFail, platformapi.ErrResponseDataFormatWrong
newErr := utils.NewErrorCode(jsonResult1["msg"].(string), code) }
if _, ok := exceedLimitCodes[code]; ok { code := jsonResult1["code"].(string)
return platformapi.ErrLevelExceedLimit, newErr if code == ResponseCodeSuccess {
} else if _, ok := canRetryCodes[code]; ok { retVal = jsonResult1
return platformapi.ErrLevelRecoverableErr, newErr return platformapi.ErrLevelSuccess, nil
} else { }
return platformapi.ErrLevelCodeIsNotOK, newErr newErr := utils.NewErrorCode(jsonResult1["msg"].(string), code)
} if _, ok := exceedLimitCodes[code]; ok {
}) return platformapi.ErrLevelExceedLimit, newErr
} else if _, ok := canRetryCodes[code]; ok {
return platformapi.ErrLevelRecoverableErr, newErr
} else {
return platformapi.ErrLevelCodeIsNotOK, newErr
}
})
return retVal, err return retVal, err
} }

View File

@@ -193,29 +193,33 @@ func (a *API) AccessAPI(action string, params map[string]interface{}) (retVal *R
params2["version"] = []string{"1.0"} params2["version"] = []string{"1.0"}
params2[signKey] = []string{a.signParams(params2)} params2[signKey] = []string{a.signParams(params2)}
// baseapi.SugarLogger.Debug(params2.Encode()) // baseapi.SugarLogger.Debug(params2.Encode())
// request, _ := http.NewRequest(http.MethodPost, mtpsAPIURL+"/"+action, strings.NewReader(params2.Encode()))
header := make(http.Header)
header.Set("Content-Type", "application/x-www-form-urlencoded")
err = platformapi.AccessPlatformAPIWithRetry(a.client, http.MethodPost, mtpsAPIURL+"/"+action, params2.Encode(), header, a.config, func(response *http.Response) (result string, err error) { err = platformapi.AccessPlatformAPIWithRetry(a.client,
jsonResult1, err := utils.HTTPResponse2Json(response) func() *http.Request {
if err != nil { request, _ := http.NewRequest(http.MethodPost, mtpsAPIURL+"/"+action, strings.NewReader(params2.Encode()))
return platformapi.ErrLevelGeneralFail, platformapi.ErrResponseDataFormatWrong request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
} return request
code := int(utils.MustInterface2Int64(jsonResult1["code"])) },
retVal = &ResponseResult{ a.config,
Code: code, func(response *http.Response) (result string, err error) {
} jsonResult1, err := utils.HTTPResponse2Json(response)
if code == ResponseCodeSuccess { if err != nil {
if innerData, ok := jsonResult1["data"]; ok { return platformapi.ErrLevelGeneralFail, platformapi.ErrResponseDataFormatWrong
retVal.Data, _ = innerData.(map[string]interface{})
} }
return platformapi.ErrLevelSuccess, nil code := int(utils.MustInterface2Int64(jsonResult1["code"]))
} retVal = &ResponseResult{
retVal.Message = jsonResult1["message"].(string) Code: code,
newErr := utils.NewErrorIntCode(retVal.Message, code) }
return platformapi.ErrLevelCodeIsNotOK, newErr if code == ResponseCodeSuccess {
}) if innerData, ok := jsonResult1["data"]; ok {
retVal.Data, _ = innerData.(map[string]interface{})
}
return platformapi.ErrLevelSuccess, nil
}
retVal.Message = jsonResult1["message"].(string)
newErr := utils.NewErrorIntCode(retVal.Message, code)
return platformapi.ErrLevelCodeIsNotOK, newErr
})
return retVal, err return retVal, err
} }

View File

@@ -4,7 +4,6 @@ import (
"errors" "errors"
"net" "net"
"net/http" "net/http"
"strings"
"time" "time"
"github.com/fatih/structs" "github.com/fatih/structs"
@@ -73,19 +72,11 @@ func init() {
structs.DefaultTagName = "json" structs.DefaultTagName = "json"
} }
func AccessPlatformAPIWithRetry(client *http.Client, method, requestURL, body string, header http.Header, config *APIConfig, handleResponse func(response *http.Response) (string, error)) error { func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.Request, config *APIConfig, handleResponse func(response *http.Response) (string, error)) error {
exceedLimitRetryCount := 0 exceedLimitRetryCount := 0
recoverableErrorRetryCount := 0 recoverableErrorRetryCount := 0
var request *http.Request
for { for {
if body != "" { request := handleRequest()
request, _ = http.NewRequest(method, requestURL, strings.NewReader(body))
} else {
request, _ = http.NewRequest(method, requestURL, nil)
}
if header != nil {
request.Header = header
}
response, err := client.Do(request) response, err := client.Do(request)
if err != nil { if err != nil {
baseapi.SugarLogger.Debugf("AccessPlatformAPIWithRetry client.Get return err:%v", err) baseapi.SugarLogger.Debugf("AccessPlatformAPIWithRetry client.Get return err:%v", err)

View File

@@ -2,6 +2,7 @@ package weixinapi
import ( import (
"net/http" "net/http"
"strings"
"sync" "sync"
"git.rosy.net.cn/baseapi/platformapi" "git.rosy.net.cn/baseapi/platformapi"
@@ -90,43 +91,46 @@ func (a *API) AccessAPI(action string, params map[string]interface{}, body strin
} }
fullURL := utils.GenerateGetURL(prodURL, action, params2) fullURL := utils.GenerateGetURL(prodURL, action, params2)
// baseapi.SugarLogger.Debug(fullURL) // baseapi.SugarLogger.Debug(fullURL)
// var request *http.Request
var method string err = platformapi.AccessPlatformAPIWithRetry(a.client,
if body == "" { func() *http.Request {
method = http.MethodGet var request *http.Request
// request, _ = http.NewRequest(http.MethodGet, fullURL, nil) if body == "" {
} else { request, _ = http.NewRequest(http.MethodGet, fullURL, nil)
method = http.MethodPost } else {
// request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(body)) request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(body))
}
// request.Close = true // todo try to fix EOF error when accessing weixin api.
err = platformapi.AccessPlatformAPIWithRetry(a.client, method, fullURL, body, nil, a.config, func(response *http.Response) (result string, err error) {
jsonResult1, err := utils.HTTPResponse2Json(response)
if err != nil {
return platformapi.ErrLevelGeneralFail, platformapi.ErrResponseDataFormatWrong
}
var errInfo *ErrorInfo
// 微信的返回值,在错误与正常情况下,结构是完全不一样的
if errCode, ok := jsonResult1["errcode"]; ok {
errInfo = &ErrorInfo{
ErrCode: int(utils.MustInterface2Int64(errCode)),
ErrMsg: jsonResult1["errmsg"].(string),
} }
if errInfo.ErrCode == 0 { request.Close = true // todo try to fix EOF error when accessing weixin api.
return request
},
a.config,
func(response *http.Response) (result string, err error) {
jsonResult1, err := utils.HTTPResponse2Json(response)
if err != nil {
return platformapi.ErrLevelGeneralFail, platformapi.ErrResponseDataFormatWrong
}
var errInfo *ErrorInfo
// 微信的返回值,在错误与正常情况下,结构是完全不一样的
if errCode, ok := jsonResult1["errcode"]; ok {
errInfo = &ErrorInfo{
ErrCode: int(utils.MustInterface2Int64(errCode)),
ErrMsg: jsonResult1["errmsg"].(string),
}
if errInfo.ErrCode == 0 {
retVal = jsonResult1
}
} else {
retVal = jsonResult1 retVal = jsonResult1
} }
} else { if retVal != nil {
retVal = jsonResult1 return platformapi.ErrLevelSuccess, nil
} }
if retVal != nil { newErr := utils.NewErrorIntCode(errInfo.ErrMsg, errInfo.ErrCode)
return platformapi.ErrLevelSuccess, nil if errInfo.ErrCode == ResponseCodeBusy {
} return platformapi.ErrLevelRecoverableErr, newErr
newErr := utils.NewErrorIntCode(errInfo.ErrMsg, errInfo.ErrCode) }
if errInfo.ErrCode == ResponseCodeBusy { return platformapi.ErrLevelCodeIsNotOK, newErr
return platformapi.ErrLevelRecoverableErr, newErr })
}
return platformapi.ErrLevelCodeIsNotOK, newErr
})
return retVal, err return retVal, err
} }