diff --git a/client.go b/client.go index 9ffc4dd0..c5080378 100644 --- a/client.go +++ b/client.go @@ -302,20 +302,14 @@ func (c *Client) SetAuthToken(token string) *Client { // R method creates a request instance, its used for Get, Post, Put, Delete, Patch, Head and Options. func (c *Client) R() *Request { r := &Request{ - URL: "", - Method: "", - QueryParam: url.Values{}, - FormData: url.Values{}, - Header: http.Header{}, - Body: nil, - Result: nil, - Error: nil, - RawRequest: nil, + QueryParam: url.Values{}, + FormData: url.Values{}, + Header: http.Header{}, + client: c, - bodyBuf: nil, multipartFiles: []*File{}, multipartFields: []*multipartField{}, - pathParams: make(map[string]string), + pathParams: map[string]string{}, } return r @@ -572,7 +566,7 @@ func (c *Client) Mode() string { func (c *Client) SetTLSClientConfig(config *tls.Config) *Client { transport, err := c.getTransport() if err != nil { - c.Log.Printf("ERROR [%v]", err) + c.Log.Printf("ERROR %v", err) return c } transport.TLSClientConfig = config @@ -588,17 +582,17 @@ func (c *Client) SetTLSClientConfig(config *tls.Config) *Client { func (c *Client) SetProxy(proxyURL string) *Client { transport, err := c.getTransport() if err != nil { - c.Log.Printf("ERROR [%v]", err) + c.Log.Printf("ERROR %v", err) return c } + if pURL, err := url.Parse(proxyURL); err == nil { c.proxyURL = pURL transport.Proxy = http.ProxyURL(c.proxyURL) } else { - c.Log.Printf("ERROR [%v]", err) + c.Log.Printf("ERROR %v", err) c.RemoveProxy() } - return c } @@ -608,7 +602,7 @@ func (c *Client) SetProxy(proxyURL string) *Client { func (c *Client) RemoveProxy() *Client { transport, err := c.getTransport() if err != nil { - c.Log.Printf("ERROR [%v]", err) + c.Log.Printf("ERROR %v", err) return c } c.proxyURL = nil @@ -621,7 +615,7 @@ func (c *Client) RemoveProxy() *Client { func (c *Client) SetCertificates(certs ...tls.Certificate) *Client { config, err := c.getTLSConfig() if err != nil { - c.Log.Printf("ERROR [%v]", err) + c.Log.Printf("ERROR %v", err) return c } config.Certificates = append(config.Certificates, certs...) @@ -634,13 +628,13 @@ func (c *Client) SetCertificates(certs ...tls.Certificate) *Client { func (c *Client) SetRootCertificate(pemFilePath string) *Client { rootPemData, err := ioutil.ReadFile(pemFilePath) if err != nil { - c.Log.Printf("ERROR [%v]", err) + c.Log.Printf("ERROR %v", err) return c } config, err := c.getTLSConfig() if err != nil { - c.Log.Printf("ERROR [%v]", err) + c.Log.Printf("ERROR %v", err) return c } if config.RootCAs == nil { @@ -665,7 +659,7 @@ func (c *Client) SetOutputDirectory(dirPath string) *Client { // SetTransport method sets custom `*http.Transport` or any `http.RoundTripper` // compatible interface implementation in the resty client. // -// Please Note: +// NOTE: // // - If transport is not type of `*http.Transport` then you may not be able to // take advantage of some of the `resty` client settings. diff --git a/middleware.go b/middleware.go index 213e188a..ac12eb78 100644 --- a/middleware.go +++ b/middleware.go @@ -226,12 +226,9 @@ func requestLogger(c *Client, r *Request) error { reqLog := "\n---------------------- REQUEST LOG -----------------------\n" + fmt.Sprintf("%s %s %s\n", r.Method, rr.URL.RequestURI(), rr.Proto) + fmt.Sprintf("HOST : %s\n", rr.URL.Host) + - fmt.Sprintf("HEADERS:\n") - - for h, v := range rr.Header { - reqLog += fmt.Sprintf("%25s: %v\n", h, strings.Join(v, ", ")) - } - reqLog += fmt.Sprintf("BODY :\n%v\n", r.fmtBodyString()) + + fmt.Sprintf("HEADERS:\n") + + composeHeaders(rr.Header) + "\n" + + fmt.Sprintf("BODY :\n%v\n", r.fmtBodyString()) + "----------------------------------------------------------\n" c.Log.Print(reqLog) @@ -250,11 +247,9 @@ func responseLogger(c *Client, res *Response) error { fmt.Sprintf("STATUS : %s\n", res.Status()) + fmt.Sprintf("RECEIVED AT : %v\n", res.ReceivedAt().Format(time.RFC3339Nano)) + fmt.Sprintf("RESPONSE TIME : %v\n", res.Time()) + - "HEADERS:\n" + "HEADERS:\n" + + composeHeaders(res.Header()) + "\n" - for h, v := range res.Header() { - resLog += fmt.Sprintf("%30s: %v\n", h, strings.Join(v, ", ")) - } if res.Request.isSaveResponse { resLog += fmt.Sprintf("BODY :\n***** RESPONSE WRITTEN INTO FILE *****\n") } else { @@ -441,14 +436,11 @@ func saveResponseIntoFile(c *Client, res *Response) error { if err != nil { return err } - defer func() { - _ = outFile.Close() - }() + defer closeq(outFile) // io.Copy reads maximum 32kb size, it is perfect for large file download too - defer func() { - _ = res.RawResponse.Body.Close() - }() + defer closeq(res.RawResponse.Body) + written, err := io.Copy(outFile, res.RawResponse.Body) if err != nil { return err diff --git a/request.go b/request.go index 54f77293..a5685e5b 100644 --- a/request.go +++ b/request.go @@ -118,7 +118,7 @@ func (r *Request) SetQueryString(query string) *Request { } } } else { - r.client.Log.Printf("ERROR [%v]", err) + r.client.Log.Printf("ERROR %v", err) } return r } @@ -471,7 +471,7 @@ func (r *Request) Execute(method, url string) (*Response, error) { resp, err = r.client.execute(r) if err != nil { - r.client.Log.Printf("ERROR [%v] Attempt [%v]", err, attempt) + r.client.Log.Printf("ERROR %v, Attempt %v", err, attempt) if r.isContextCancelledIfAvailable() { // stop Backoff from retrying request if request has been // canceled by context diff --git a/request16.go b/request16.go index 1e229b7f..a61a7c02 100644 --- a/request16.go +++ b/request16.go @@ -17,36 +17,35 @@ import ( // Request type is used to compose and send individual request from client // go-resty is provide option override client level settings such as -// Auth Token, Basic Auth credentials, Header, Query Param, Form Data, Error object +// Auth Token, Basic Auth credentials, Header, Query Param, Form Data, Error object // and also you can add more options for that particular request -// type Request struct { URL string Method string + Token string QueryParam url.Values FormData url.Values Header http.Header - UserInfo *User - Token string + Time time.Time Body interface{} Result interface{} Error interface{} - Time time.Time RawRequest *http.Request SRV *SRVRecord + UserInfo *User - client *Client - bodyBuf *bytes.Buffer isMultiPart bool isFormData bool setContentLength bool isSaveResponse bool - outputFile string - multipartFiles []*File - multipartFields []*multipartField notParseResponse bool + outputFile string fallbackContentType string pathParams map[string]string + client *Client + bodyBuf *bytes.Buffer + multipartFiles []*File + multipartFields []*multipartField } func (r *Request) addContextIfAvailable() { diff --git a/request17.go b/request17.go index 30ddc448..5e0f3b3e 100644 --- a/request17.go +++ b/request17.go @@ -18,37 +18,36 @@ import ( // Request type is used to compose and send individual request from client // go-resty is provide option override client level settings such as -// Auth Token, Basic Auth credentials, Header, Query Param, Form Data, Error object +// Auth Token, Basic Auth credentials, Header, Query Param, Form Data, Error object // and also you can add more options for that particular request -// type Request struct { URL string Method string + Token string QueryParam url.Values FormData url.Values Header http.Header - UserInfo *User - Token string + Time time.Time Body interface{} Result interface{} Error interface{} - Time time.Time RawRequest *http.Request SRV *SRVRecord + UserInfo *User - client *Client - bodyBuf *bytes.Buffer isMultiPart bool isFormData bool setContentLength bool isSaveResponse bool - outputFile string - multipartFiles []*File - multipartFields []*multipartField notParseResponse bool - ctx context.Context + outputFile string fallbackContentType string + ctx context.Context pathParams map[string]string + client *Client + bodyBuf *bytes.Buffer + multipartFiles []*File + multipartFields []*multipartField } // SetContext method sets the context.Context for current Request. It allows diff --git a/request_test.go b/request_test.go index 43aa6d05..e909ca31 100644 --- a/request_test.go +++ b/request_test.go @@ -1398,7 +1398,7 @@ func TestPathParamURLInput(t *testing.T) { ts := createGetServer(t) defer ts.Close() - c := dc() + c := dc().SetDebug(true) c.SetHostURL(ts.URL). SetPathParams(map[string]string{ "userId": "sample@sample.com", diff --git a/util.go b/util.go index 88e56533..db16edc2 100644 --- a/util.go +++ b/util.go @@ -18,6 +18,7 @@ import ( "path/filepath" "reflect" "runtime" + "sort" "strings" ) @@ -150,10 +151,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error { if err != nil { return err } - defer func() { - _ = file.Close() - }() - + defer closeq(file) return writeMultipartFormFile(w, fieldName, filepath.Base(path), file) } @@ -221,6 +219,25 @@ func releaseBuffer(buf *bytes.Buffer) { func closeq(v interface{}) { if c, ok := v.(io.Closer); ok { - _ = c.Close() + sliently(c.Close()) + } +} + +func sliently(_ ...interface{}) {} + +func composeHeaders(hdrs http.Header) string { + var str []string + for _, k := range sortHeaderKeys(hdrs) { + str = append(str, fmt.Sprintf("%25s: %s", k, strings.Join(hdrs[k], ", "))) + } + return strings.Join(str, "\n") +} + +func sortHeaderKeys(hdrs http.Header) []string { + var keys []string + for key := range hdrs { + keys = append(keys, key) } + sort.Strings(keys) + return keys }