Compare commits

..

1 Commits

Author SHA1 Message Date
nanhe 1233c07df9 feat: support custom httpClient 2025-03-26 17:59:12 +08:00
4 changed files with 28 additions and 142 deletions
+18 -48
View File
@@ -34,28 +34,8 @@ type RuntimeOptions = util.RuntimeOptions
type ExtendsParameters = util.ExtendsParameters
var debugLog = debug.Init("dara")
type HttpRequest interface {
}
type HttpResponse interface {
}
type HttpClient interface {
Call(request *http.Request, transport *http.Transport) (response *http.Response, err error)
}
type daraClient struct {
sync.Mutex
httpClient *http.Client
ifInit bool
}
func (client *daraClient) Call(request *http.Request, transport *http.Transport) (response *http.Response, err error) {
response, err = client.httpClient.Do(request)
return
}
var hookDo = func(fn func(req *http.Request, transport *http.Transport) (*http.Response, error)) func(req *http.Request, transport *http.Transport) (*http.Response, error) {
var hookDo = func(fn func(req *http.Request) (*http.Response, error)) func(req *http.Request) (*http.Response, error) {
return fn
}
@@ -108,7 +88,12 @@ type RuntimeObject struct {
Logger *utils.Logger `json:"logger" xml:"logger"`
RetryOptions *RetryOptions `json:"retryOptions" xml:"retryOptions"`
ExtendsParameters *ExtendsParameters `json:"extendsParameters,omitempty" xml:"extendsParameters,omitempty"`
HttpClient
}
type daraClient struct {
sync.Mutex
httpClient *http.Client
ifInit bool
}
func (r *RuntimeObject) getClientTag(domain string) string {
@@ -147,12 +132,6 @@ func NewRuntimeObject(runtime map[string]interface{}) *RuntimeObject {
if runtime["logger"] != nil {
runtimeObject.Logger = runtime["logger"].(*utils.Logger)
}
if runtime["httpClient"] != nil {
runtimeObject.HttpClient = runtime["httpClient"].(HttpClient)
}
if runtime["retryOptions"] != nil {
runtimeObject.RetryOptions = runtime["retryOptions"].(*RetryOptions)
}
return runtimeObject
}
@@ -271,27 +250,18 @@ func DoRequest(request *Request, runtimeObject *RuntimeObject) (response *Respon
}
httpRequest.Host = StringValue(request.Domain)
var client HttpClient
if runtimeObject.HttpClient == nil {
client = getDaraClient(runtimeObject.getClientTag(StringValue(request.Domain)))
} else {
client = runtimeObject.HttpClient
}
trans, err := getHttpTransport(request, runtimeObject)
if err != nil {
return
}
if defaultClient, ok := client.(*daraClient); ok {
defaultClient.Lock()
if !defaultClient.ifInit || defaultClient.httpClient.Transport == nil {
defaultClient.httpClient.Transport = trans
client := getDaraClient(runtimeObject.getClientTag(StringValue(request.Domain)))
client.Lock()
if !client.ifInit {
trans, err := getHttpTransport(request, runtimeObject)
if err != nil {
return nil, err
}
defaultClient.httpClient.Timeout = time.Duration(IntValue(runtimeObject.ReadTimeout)) * time.Millisecond
defaultClient.ifInit = true
defaultClient.Unlock()
client.httpClient.Timeout = time.Duration(IntValue(runtimeObject.ReadTimeout)) * time.Millisecond
client.httpClient.Transport = trans
client.ifInit = true
}
client.Unlock()
for key, value := range request.Headers {
if value == nil || key == "content-length" {
continue
@@ -313,7 +283,7 @@ func DoRequest(request *Request, runtimeObject *RuntimeObject) (response *Respon
putMsgToMap(fieldMap, httpRequest)
startTime := time.Now()
fieldMap["{start_time}"] = startTime.Format("2006-01-02 15:04:05")
res, err := hookDo(client.Call)(httpRequest, trans)
res, err := hookDo(client.httpClient.Do)(httpRequest)
fieldMap["{cost}"] = time.Since(startTime).String()
completedBytes := int64(0)
if runtimeObject.Tracker != nil {
+10 -51
View File
@@ -30,12 +30,6 @@ var runtimeObj = map[string]interface{}{
"listener": &Progresstest{},
"tracker": &utils.ReaderTracker{CompletedBytes: int64(10)},
"logger": utils.NewLogger("info", "", &bytes.Buffer{}, "{time}"),
"retryOptions": &RetryOptions{
Retryable: true,
RetryCondition: []*RetryCondition{
{MaxAttempts: 3, Exception: []string{"AErr"}, ErrorCode: []string{"A1Err"}},
},
},
}
var key = `-----BEGIN RSA PRIVATE KEY-----
@@ -199,10 +193,6 @@ func TestRuntimeObject(t *testing.T) {
runtimeobject = NewRuntimeObject(runtimeObj)
utils.AssertEqual(t, false, BoolValue(runtimeobject.IgnoreSSL))
utils.AssertEqual(t, true, runtimeobject.RetryOptions.Retryable)
utils.AssertEqual(t, 1, len(runtimeobject.RetryOptions.RetryCondition))
}
func TestSDKError(t *testing.T) {
@@ -498,36 +488,12 @@ func Test_GetBackoffTime(t *testing.T) {
ms = GetBackoffTime(backoff, Int(1))
utils.AssertEqual(t, true, IntValue(ms) <= 3)
}
type httpClient struct {
HttpClient
httpClient *http.Client
}
func newHttpClient() (*httpClient, error) {
client := new(httpClient)
err := client.Init()
return client, err
}
func (client *httpClient) Init() (_err error) {
return nil
}
func (client *httpClient) Call(request *http.Request, transport *http.Transport) (_result *http.Response, _err error) {
if transport != nil {
trans := transport.Clone()
client.httpClient.Transport = trans
} else {
client.httpClient.Transport = http.DefaultTransport.(*http.Transport).Clone()
}
return client.httpClient.Do(request)
}
func Test_DoRequest(t *testing.T) {
origTestHookDo := hookDo
defer func() { hookDo = origTestHookDo }()
hookDo = func(fn func(req *http.Request, transport *http.Transport) (*http.Response, error)) func(req *http.Request, transport *http.Transport) (*http.Response, error) {
return func(req *http.Request, transport *http.Transport) (*http.Response, error) {
hookDo = func(fn func(req *http.Request) (*http.Response, error)) func(req *http.Request) (*http.Response, error) {
return func(req *http.Request) (*http.Response, error) {
return mockResponse(200, ``, errors.New("Internal error"))
}
}
@@ -566,8 +532,8 @@ func Test_DoRequest(t *testing.T) {
utils.AssertNil(t, resp)
utils.AssertContains(t, err.Error(), ` invalid URL escape "%gf"`)
hookDo = func(fn func(req *http.Request, transport *http.Transport) (*http.Response, error)) func(req *http.Request, transport *http.Transport) (*http.Response, error) {
return func(req *http.Request, transport *http.Transport) (*http.Response, error) {
hookDo = func(fn func(req *http.Request) (*http.Response, error)) func(req *http.Request) (*http.Response, error) {
return func(req *http.Request) (*http.Response, error) {
return mockResponse(200, ``, nil)
}
}
@@ -615,8 +581,8 @@ func Test_DoRequest(t *testing.T) {
utils.AssertNil(t, err)
utils.AssertEqual(t, "test", StringValue(resp.Headers["tea"]))
hookDo = func(fn func(req *http.Request, transport *http.Transport) (*http.Response, error)) func(req *http.Request, transport *http.Transport) (*http.Response, error) {
return func(req *http.Request, transport *http.Transport) (*http.Response, error) {
hookDo = func(fn func(req *http.Request) (*http.Response, error)) func(req *http.Request) (*http.Response, error) {
return func(req *http.Request) (*http.Response, error) {
utils.AssertEqual(t, "tea-cn-hangzhou.aliyuncs.com:1080", req.Host)
return mockResponse(200, ``, errors.New("Internal error"))
}
@@ -628,20 +594,13 @@ func Test_DoRequest(t *testing.T) {
resp, err = DoRequest(request, NewRuntimeObject(runtimeObj))
utils.AssertNil(t, resp)
utils.AssertEqual(t, `Internal error`, err.Error())
httpClient, err := newHttpClient()
utils.AssertNil(t, err)
runtimeObj["httpClient"] = httpClient
resp, err = DoRequest(request, NewRuntimeObject(runtimeObj))
utils.AssertNil(t, resp)
utils.AssertEqual(t, `Internal error`, err.Error())
}
func Test_DoRequestWithConcurrent(t *testing.T) {
origTestHookDo := hookDo
defer func() { hookDo = origTestHookDo }()
hookDo = func(fn func(req *http.Request, transport *http.Transport) (*http.Response, error)) func(req *http.Request, transport *http.Transport) (*http.Response, error) {
return func(req *http.Request, transport *http.Transport) (*http.Response, error) {
hookDo = func(fn func(req *http.Request) (*http.Response, error)) func(req *http.Request) (*http.Response, error) {
return func(req *http.Request) (*http.Response, error) {
return mockResponse(200, ``, nil)
}
}
@@ -737,11 +696,11 @@ func Test_SetDialContext(t *testing.T) {
}
func Test_hookdo(t *testing.T) {
fn := func(req *http.Request, transport *http.Transport) (*http.Response, error) {
fn := func(req *http.Request) (*http.Response, error) {
return nil, errors.New("hookdo")
}
result := hookDo(fn)
resp, err := result(nil, nil)
resp, err := result(nil)
utils.AssertNil(t, resp)
utils.AssertEqual(t, "hookdo", err.Error())
}
-35
View File
@@ -1,35 +0,0 @@
{
"scope": "darabonba",
"name": "HttpClientV2",
"version": "0.0.1",
"main": "./main.dara",
"maintainers": [
{
"name": "Alibaba Cloud SDK",
"email": "sdk-team@alibabacloud.com"
}
],
"libraries": {
},
"releases": {
"go": "github.com/alibabacloud-go/tea/dara:v1.3.5"
},
"go": {
"interface": true,
"clientName": "HttpClient",
"typedef": {
"HttpRequest": {
"import": "net/http",
"type": "http.Request"
},
"HttpResponse": {
"import": "net/http",
"type": "http.Response"
},
"HttpTransport": {
"import": "net/http",
"type": "http.Transport"
}
}
}
}
-8
View File
@@ -1,8 +0,0 @@
typedef HttpRequest;
typedef HttpResponse;
typedef HttpTransport;
init(){
}
async function call(request: HttpRequest, transport: HttpTransport): HttpResponse;