From 1671f7856a07d21a0289635a2999160e792d59ab Mon Sep 17 00:00:00 2001 From: BoWen Qiu <45390913+aki-colt@users.noreply.github.com> Date: Fri, 18 Oct 2024 15:14:52 +0800 Subject: [PATCH] feat(netutil): add async http request for http client (#256) * fix(algorithm): fix bug of lrucache in issue #251 * feat(netutil): add async send request for HttpClient --- netutil/http.go | 16 ++++++++++++++++ netutil/http_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/netutil/http.go b/netutil/http.go index d0aaa682..aaa3bf25 100644 --- a/netutil/http.go +++ b/netutil/http.go @@ -221,6 +221,22 @@ func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, err return resp, nil } +// AsyncSendRequest send http request with goroutine, pop response and error to channels +func (client *HttpClient) AsyncSendRequest(request *HttpRequest, respChan chan *http.Response, errChan chan error) { + go func() { + defer func() { + if err := recover(); err != nil { + errChan <- fmt.Errorf("%v", err) + } + }() + resp, err := client.SendRequest(request) + if err != nil { + errChan <- err + } + respChan <- resp + }() +} + // DecodeResponse decode response into target object. // Play: https://go.dev/play/p/jUSgynekH7G func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error { diff --git a/netutil/http_test.go b/netutil/http_test.go index 7cad1ae6..06b24628 100644 --- a/netutil/http_test.go +++ b/netutil/http_test.go @@ -373,6 +373,45 @@ func TestSendRequestWithFilePath(t *testing.T) { } } +func TestHttpClient_AsyncSendRequest(t *testing.T) { + t.Parallel() + + assert := internal.NewAssert(t, "TestHttpClient_Get") + + request := &HttpRequest{ + RawURL: "https://jsonplaceholder.typicode.com/todos/1", + Method: "GET", + } + + httpClient := NewHttpClient() + respCh := make(chan *http.Response, 20) + errCh := make(chan error, 20) + for i := 0; i < 50; i++ { + httpClient.AsyncSendRequest(request, respCh, errCh) + } + for i := 0; i < 50; i++ { + select { + case resp := <-respCh: + type Todo struct { + UserId int `json:"userId"` + Id int `json:"id"` + Title string `json:"title"` + Completed bool `json:"completed"` + } + var todo Todo + err := httpClient.DecodeResponse(resp, &todo) + if err != nil { + t.FailNow() + } + assert.Equal(1, todo.Id) + case err := <-errCh: + if err != nil { + t.Log("net error: ", err.Error()) + } + } + } +} + func TestProxy(t *testing.T) { config := &HttpClientConfig{ HandshakeTimeout: 20 * time.Second,