From 30aeb3f99c114751a02cb8c0fd08b61b2b21f522 Mon Sep 17 00:00:00 2001 From: ahuigo <1781999+ahuigo@users.noreply.github.com> Date: Tue, 10 Oct 2023 16:22:38 +0800 Subject: [PATCH] fix(curl): getCurlCmd should not send request --- README.md | 5 +++++ client.go | 23 +++++++++++++++-------- examples/auth_test.go | 17 ++++++++++++----- examples/context_test.go | 14 ++++++-------- examples/cookie_test.go | 15 ++++++++------- examples/debug_curl_test.go | 26 ++++++++++++-------------- examples/debug_test.go | 2 +- examples/debug_trace_test.go | 5 +---- examples/delete_test.go | 2 +- examples/error_test.go | 1 + examples/get_test.go | 2 ++ examples/post_file_test.go | 8 ++++---- examples/post_test.go | 2 ++ examples/proxy_test.go | 21 +++++++++++++++------ examples/req_header_test.go | 2 +- examples/response_build_test.go | 1 + examples/response_test.go | 2 +- examples/retry_test.go | 1 + examples/ssl_test.go | 1 + examples/timeout_test.go | 1 + examples/transport_test.go | 1 + middleware.go | 4 ++-- request.go | 32 ++++++++++++++++++-------------- response.go | 9 --------- 24 files changed, 112 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 294a288f..fff0541f 100644 --- a/README.md +++ b/README.md @@ -126,12 +126,17 @@ import "github.com/go-resty/resty/v2" ```go // Create a Resty Client +var curlCmdExecuted string client := resty.New() resp, err := client.R(). + SetResultCurlCmd(&curlCmdExecuted). EnableTrace(). Get("https://httpbin.org/get") +// Explore curl command +fmt.Println("Curl Command:", curlCmdExecuted) + // Explore response object fmt.Println("Response Info:") fmt.Println(" Error :", err) diff --git a/client.go b/client.go index 728ce6a1..906f5aeb 100644 --- a/client.go +++ b/client.go @@ -1129,9 +1129,7 @@ func (c *Client) GetClient() *http.Client { // Client Unexported methods //_______________________________________________________________________ -// Executes method executes the given `Request` object and returns response -// error. -func (c *Client) execute(req *Request) (*Response, error) { +func (c *Client) executeBefore(req *Request) (error) { // Lock the user-defined pre-request hooks. c.udBeforeRequestLock.RLock() defer c.udBeforeRequestLock.RUnlock() @@ -1147,7 +1145,7 @@ func (c *Client) execute(req *Request) (*Response, error) { // to modify the *resty.Request object for _, f := range c.udBeforeRequest { if err = f(c, req); err != nil { - return nil, wrapNoRetryErr(err) + return wrapNoRetryErr(err) } } @@ -1155,14 +1153,14 @@ func (c *Client) execute(req *Request) (*Response, error) { // will return an error if the rate limit is exceeded. if req.client.rateLimiter != nil { if !req.client.rateLimiter.Allow() { - return nil, wrapNoRetryErr(ErrRateLimitExceeded) + return wrapNoRetryErr(ErrRateLimitExceeded) } } // resty middlewares for _, f := range c.beforeRequest { if err = f(c, req); err != nil { - return nil, wrapNoRetryErr(err) + return wrapNoRetryErr(err) } } @@ -1173,15 +1171,24 @@ func (c *Client) execute(req *Request) (*Response, error) { // call pre-request if defined if c.preReqHook != nil { if err = c.preReqHook(c, req.RawRequest); err != nil { - return nil, wrapNoRetryErr(err) + return wrapNoRetryErr(err) } } if err = requestLogger(c, req); err != nil { - return nil, wrapNoRetryErr(err) + return wrapNoRetryErr(err) } req.RawRequest.Body = newRequestBodyReleaser(req.RawRequest.Body, req.bodyBuf) + return nil +} + +// Executes method executes the given `Request` object and returns response +// error. +func (c *Client) execute(req *Request) (*Response, error) { + if err:= c.executeBefore(req);err!=nil{ + return nil, err + } req.Time = time.Now() resp, err := c.httpClient.Do(req.RawRequest) diff --git a/examples/auth_test.go b/examples/auth_test.go index 2df54f9f..86bfdae6 100644 --- a/examples/auth_test.go +++ b/examples/auth_test.go @@ -7,19 +7,26 @@ import ( "github.com/go-resty/resty/v3" ) - +// Example about sending Authentication header func TestAuth(t *testing.T) { + var curlCmdExecuted string ts := createEchoServer() defer ts.Close() - // test authentication usernae,password + // Test authentication usernae and password client := resty.New() - resp, err := client.R().SetBasicAuth("httpwatch", "foo").Get( ts.URL+"/echo",) + resp, err := client.R(). + SetBasicAuth("USER", "PASSWORD"). + SetResultCurlCmd(&curlCmdExecuted). + Get( ts.URL+"/echo",) if err != nil { t.Fatal(err) } + + if !strings.Contains(curlCmdExecuted, "Authorization: Basic ") { + t.Fatal("bad curl:", curlCmdExecuted) + } if !strings.Contains(string(resp.Body()), "Authorization: Basic ") { t.Fatal("bad auth body:\n" + resp.String()) } - // this save file test PASS - // resp.SaveFile("auth.jpeg") + t.Log(curlCmdExecuted) } diff --git a/examples/context_test.go b/examples/context_test.go index 26c0b36b..812aac2e 100644 --- a/examples/context_test.go +++ b/examples/context_test.go @@ -1,6 +1,3 @@ -/** - * refer to: git@github.com:go-resty/resty.git - */ package examples import ( @@ -13,8 +10,9 @@ import ( "github.com/go-resty/resty/v3" ) -// test context: cancel multi +// Example about cancel request with context func TestSetContextCancelMulti(t *testing.T) { + // 0. Init test server ts := createTestServer(func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Microsecond) n, err := w.Write([]byte("TestSetContextCancel: response")) @@ -23,7 +21,7 @@ func TestSetContextCancelMulti(t *testing.T) { }, 0) defer ts.Close() - // client + // 1. Create client ctx, cancel := context.WithCancel(context.Background()) client := resty.New().R().SetContext(ctx) go func() { @@ -31,20 +29,20 @@ func TestSetContextCancelMulti(t *testing.T) { cancel() }() - // first + // 2. First request _, err := client.Get(ts.URL + "/get") if !errIsContextCancel(err) { t.Fatalf("Got unexpected error: %v", err) } - // second + // 3. Second request _, err = client.Get(ts.URL + "/get") if !errIsContextCancel(err) { t.Fatalf("Got unexpected error: %v", err) } } -// test context: cancel with chan +// Test context: cancel with chan func TestSetContextCancelWithChan(t *testing.T) { ch := make(chan struct{}) ts := createTestServer(func(w http.ResponseWriter, r *http.Request) { diff --git a/examples/cookie_test.go b/examples/cookie_test.go index c479ee5f..a81fa6ee 100644 --- a/examples/cookie_test.go +++ b/examples/cookie_test.go @@ -8,6 +8,7 @@ import ( "github.com/go-resty/resty/v3" ) +// Example about sending cookie func TestSendCookie(t *testing.T) { ts := createHttpbinServer(0) defer ts.Close() @@ -84,7 +85,7 @@ func TestSessionCookieWithClone(t *testing.T) { client := resty.New() req := client.R() - // set cookie + // 0. Prepare cookie1 and cookie2 cookie1 := &http.Cookie{ Name: "name1", Value: "value1", @@ -95,26 +96,28 @@ func TestSessionCookieWithClone(t *testing.T) { Value: "value2", } - // 1. set cookie1 + // 1. Set cookie1 client.SetCookie(cookie1) req.SetCookie(cookie1).Get(url) - // 2. set cookie2 and get all cookies + // 2. Set cookie2 and get all cookies resp, err := req.SetCookie(cookie2).Get(url) if err != nil { t.Fatal(err) } - // 3. check cookies: client, response + // 3. Check cookies: client and response respCookies := map[string]string{} clientCookies := map[string]string{} // cookies's type is `[]*http.Cookies` + // 3.1 Check response cookies for _, c := range resp.Cookies() { if _, exists := respCookies[c.Name]; exists { t.Fatal("duplicated cookie:", c.Name, c.Value) } respCookies[c.Name] = c.Value } + // 3.2 Check client cookies for _, c := range client.Cookies { if _, exists := clientCookies[c.Name]; exists { t.Fatal("duplicated cookie:", c.Name, c.Value) @@ -125,7 +128,7 @@ func TestSessionCookieWithClone(t *testing.T) { t.Fatalf("bad cookie, respCookies=%+v, clientCookies=%+v", resp.Cookies(), client.Cookies) } - // 4. check response body + // 4. Check response body body := resp.String() if (!strings.Contains(body, `"name1"`) || !strings.Contains(body, `"name2"`) || @@ -140,8 +143,6 @@ func TestResponseCookie(t *testing.T) { ts := createHttpbinServer(0) defer ts.Close() - // resp, err := requests.Get("https://httpbin.org/json") - session := resty.New().R() resp, err := session.Get(ts.URL + "/cookie/count") if err != nil { diff --git a/examples/debug_curl_test.go b/examples/debug_curl_test.go index 31490e6a..301e4e0f 100644 --- a/examples/debug_curl_test.go +++ b/examples/debug_curl_test.go @@ -8,7 +8,7 @@ import ( "github.com/go-resty/resty/v3" ) - +// Example about generating curl command func TestDebugCurl(t *testing.T) { ts := createHttpbinServer(0) defer ts.Close() @@ -19,23 +19,21 @@ func TestDebugCurl(t *testing.T) { []*http.Cookie{ { Name: "count", Value: "1", }, }, - ).EnableCurl() + ) - // 1. generate curl before request - curl_before_req := req.GetCurlCmd() - if !strings.Contains(curl_before_req, "Cookie: count=1") || !strings.Contains(curl_before_req, "curl -X GET") { - t.Fatal("bad curl:", curl_before_req) + // 1. Generate curl for request(not executed) + curlCmdUnexecuted := req.GetCurlCmd() + if !strings.Contains(curlCmdUnexecuted, "Cookie: count=1") || !strings.Contains(curlCmdUnexecuted, "curl -X GET") { + t.Fatal("bad curl:", curlCmdUnexecuted) } - // 2. send request - resp, err := req.Post(ts.URL+"/post",) - if err != nil { + // 2. Generate curl for request(executed) + var curlCmdExecuted string + req.SetResultCurlCmd(&curlCmdExecuted) + if _, err := req.Post(ts.URL+"/post"); err != nil { t.Fatal(err) } - - // 3. generate curl after request - curl_after_req := resp.Request.GetCurlCmd() - if !strings.Contains(curl_after_req, "Cookie: count=1") || !strings.Contains(curl_after_req, "curl -X POST") { - t.Fatal("bad curl:", curl_after_req) + if !strings.Contains(curlCmdExecuted, "Cookie: count=1") || !strings.Contains(curlCmdExecuted, "curl -X POST") { + t.Fatal("bad curl:", curlCmdExecuted) } } \ No newline at end of file diff --git a/examples/debug_test.go b/examples/debug_test.go index 6f077deb..9b3b8e04 100644 --- a/examples/debug_test.go +++ b/examples/debug_test.go @@ -6,7 +6,7 @@ import ( "github.com/go-resty/resty/v3" ) - +// Example about debuging/showing request and response func TestDebugRequestAndResponse(t *testing.T) { ts := createHttpbinServer(0) defer ts.Close() diff --git a/examples/debug_trace_test.go b/examples/debug_trace_test.go index 22b5932a..9d2dd58a 100644 --- a/examples/debug_trace_test.go +++ b/examples/debug_trace_test.go @@ -1,6 +1,3 @@ -/** - * refer to: git@github.com:go-resty/resty.git - */ package examples import ( @@ -9,7 +6,7 @@ import ( "github.com/go-resty/resty/v3" ) -// test context: cancel multi +// Example about getting trace info func TestTrace(t *testing.T) { ts := createHttpbinServer(0) defer ts.Close() diff --git a/examples/delete_test.go b/examples/delete_test.go index 4a9ec82f..3fc49593 100644 --- a/examples/delete_test.go +++ b/examples/delete_test.go @@ -7,7 +7,7 @@ import ( "github.com/go-resty/resty/v3" ) -// Delete Form Request +// Example about DELETE method with Form Request func TestDeleteForm(t *testing.T) { ts := createHttpbinServer(0) defer ts.Close() diff --git a/examples/error_test.go b/examples/error_test.go index 33465cda..c2eb12f7 100644 --- a/examples/error_test.go +++ b/examples/error_test.go @@ -11,6 +11,7 @@ import ( "github.com/go-resty/resty/v3" ) +// Example about error handling func TestErrorConnnect(t *testing.T) { _, err := resty.New().R().Get("http://127.0.0.1:12346/connect-refused") var err2 *url.Error diff --git a/examples/get_test.go b/examples/get_test.go index 84d7a45b..3f92d8d7 100644 --- a/examples/get_test.go +++ b/examples/get_test.go @@ -9,6 +9,8 @@ import ( var client = resty.New() +// Example about sending GET request + // Get example: fetch json response func TestGetJson(t *testing.T) { ts := createHttpbinServer(0) diff --git a/examples/post_file_test.go b/examples/post_file_test.go index 9d008660..ea910f9e 100644 --- a/examples/post_file_test.go +++ b/examples/post_file_test.go @@ -8,8 +8,8 @@ import ( ) /* -An example about post both `file` and `form data`: -curl "https://www.httpbin.org/post" -F 'file1=@./test-file.txt' -F 'file2=@./version' -F 'name=alex' +An example about post `file` with `form data`: +curl "https://www.httpbin.org/post" -F 'file1=@./test-file.txt' -F 'name=alex' */ func TestPostFile(t *testing.T) { ts := createHttpbinServer(0) @@ -30,13 +30,13 @@ func TestPostFile(t *testing.T) { SetFile("file1", filepath.Join(getTestDataPath(),"text-file.txt")). SetResult(&data) - // 2. post file + // 2. Post file resp, err := r.Post( ts.URL+"/file",) if err != nil { t.Fatal(err) } - // 3. check response + // 3. Check response if data.Files.File1 == "" { t.Error("invalid response files:", resp.String()) } diff --git a/examples/post_test.go b/examples/post_test.go index 53cb4124..9228bd85 100644 --- a/examples/post_test.go +++ b/examples/post_test.go @@ -10,6 +10,8 @@ import ( "github.com/go-resty/resty/v3" ) +// Example about sending POST request + // Post Params: use with content-type: none // curl -X POST "https://www.httpbin.org/post?name=Alex" func TestPostParams(t *testing.T) { diff --git a/examples/proxy_test.go b/examples/proxy_test.go index fcdec34f..4dfdfc4d 100644 --- a/examples/proxy_test.go +++ b/examples/proxy_test.go @@ -2,13 +2,22 @@ package examples import ( "testing" + + "github.com/go-resty/resty/v3" ) +// Example about using proxy func TestProxy(t *testing.T) { - println("5. Get: with proxy") - /* todo - session := requests.R() - session.SetProxy("http://192.168.1.190:8888") - session.Get("https://www.httpbin.org/cookies/set?freeform=1234") - */ + ts := createHttpbinServer(0) + defer ts.Close() + + var json map[string]interface{} + client := resty.New().SetProxy("http://proxy:8888") + client.RemoveProxy() // remove proxy. TODO: mock proxy server in future + _, err := client.R().SetResult(&json).Get(ts.URL + "/get") + if err != nil { + t.Fatal(err) + }else { + t.Logf("response json:%#v\n", json) + } } diff --git a/examples/req_header_test.go b/examples/req_header_test.go index 50378102..6a93608c 100644 --- a/examples/req_header_test.go +++ b/examples/req_header_test.go @@ -6,7 +6,7 @@ import ( "github.com/go-resty/resty/v3" ) -// Send headers +// Example about sending headers func TestSendHeader(t *testing.T) { ts := createHttpbinServer(0) defer ts.Close() diff --git a/examples/response_build_test.go b/examples/response_build_test.go index 720ee316..2b9de547 100644 --- a/examples/response_build_test.go +++ b/examples/response_build_test.go @@ -10,6 +10,7 @@ import ( "github.com/go-resty/resty/v3" ) +// Example about building response func TestResponseBuilder(t *testing.T) { var err error var data = 1 diff --git a/examples/response_test.go b/examples/response_test.go index 283ff966..6222e537 100644 --- a/examples/response_test.go +++ b/examples/response_test.go @@ -7,7 +7,7 @@ import ( "github.com/go-resty/resty/v3" ) -// Test Response +// Example about using response func TestResponse(t *testing.T) { ts := createHttpbinServer(0) defer ts.Close() diff --git a/examples/retry_test.go b/examples/retry_test.go index 94ed75f2..3b2ea530 100644 --- a/examples/retry_test.go +++ b/examples/retry_test.go @@ -8,6 +8,7 @@ import ( "github.com/go-resty/resty/v3" ) +// Example about retrying request func TestRetryCondition(t *testing.T) { ts := createHttpbinServer(0) defer ts.Close() diff --git a/examples/ssl_test.go b/examples/ssl_test.go index 6b46ffd7..2f9a949d 100644 --- a/examples/ssl_test.go +++ b/examples/ssl_test.go @@ -12,6 +12,7 @@ import ( "github.com/go-resty/resty/v3" ) +// Example about ssl func TestSkipSsl(t *testing.T) { // 1. create tls test server ts := createHttpbinServer(2) diff --git a/examples/timeout_test.go b/examples/timeout_test.go index c600a793..8f7432fe 100644 --- a/examples/timeout_test.go +++ b/examples/timeout_test.go @@ -8,6 +8,7 @@ import ( "github.com/go-resty/resty/v3" ) +// Example about setting timeout func TestTimeout(t *testing.T) { ts := createHttpbinServer(0) defer ts.Close() diff --git a/examples/transport_test.go b/examples/transport_test.go index e6517e3d..fb887fb4 100644 --- a/examples/transport_test.go +++ b/examples/transport_test.go @@ -10,6 +10,7 @@ import ( "github.com/go-resty/resty/v3" ) +// Example about using custom transport func TestTransportSet(t *testing.T) { ts := createHttpbinServer(0) defer ts.Close() diff --git a/middleware.go b/middleware.go index e69ff8f4..8a3b56f7 100644 --- a/middleware.go +++ b/middleware.go @@ -308,8 +308,8 @@ func addCredentials(c *Client, r *Request) error { } func createCurlCmd(c *Client, r *Request) (err error) { - if r.enableCurl{ - r.curlCmd = BuildCurlRequest(r.RawRequest, c.httpClient.Jar) + if r.resultCurlCmd!=nil{ + *r.resultCurlCmd = BuildCurlRequest(r.RawRequest, c.httpClient.Jar) } return nil } diff --git a/request.go b/request.go index 59b8c11b..0031990f 100644 --- a/request.go +++ b/request.go @@ -39,6 +39,7 @@ type Request struct { Time time.Time Body interface{} Result interface{} + resultCurlCmd *string Error interface{} RawRequest *http.Request SRV *SRVRecord @@ -71,23 +72,20 @@ type Request struct { multipartFiles []*File multipartFields []*MultipartField retryConditions []RetryConditionFunc - enableCurl bool - curlCmd string } -func (r *Request) EnableCurl() *Request{ - r.enableCurl = true - return r -} - -func (r *Request) GetCurlCmd() string{ - if r.curlCmd == ""{ - if r.RawRequest == nil{ - r.Get("/") +func (r *Request) GetCurlCmd() string { + // trigger beforeRequest from middleware + if r.RawRequest == nil { + r.client.executeBefore(r) // mock r.Get("/") } - r.curlCmd = BuildCurlRequest(r.RawRequest, r.client.httpClient.Jar) - } - return r.curlCmd + if r.resultCurlCmd == nil { + r.resultCurlCmd = new(string) + } + if *r.resultCurlCmd == "" { + *r.resultCurlCmd = BuildCurlRequest(r.RawRequest, r.client.httpClient.Jar) + } + return *r.resultCurlCmd } // Context method returns the Context if its already set in request @@ -350,6 +348,12 @@ func (r *Request) SetResult(res interface{}) *Request { return r } +// This method is to register curl cmd for request executed. +func (r *Request) SetResultCurlCmd(curlCmd *string) *Request { + r.resultCurlCmd = curlCmd + return r +} + // SetError method is to register the request `Error` object for automatic unmarshalling for the request, // if response status code is greater than 399 and content type either JSON or XML. // diff --git a/response.go b/response.go index 8025f26b..63c95c41 100644 --- a/response.go +++ b/response.go @@ -103,15 +103,6 @@ func (r *Response) Cookies() []*http.Cookie { return r.RawResponse.Cookies() } -func (r *Response) GetCookie(key string) (string) { - for _, c := range r.Cookies() { - if c.Name==key{ - return c.Value - } - } - return "" -} - // String method returns the body of the server response as String. func (r *Response) String() string { if len(r.body) == 0 {