Skip to content

Commit

Permalink
Merge branch 'master' into fix/data-race-restore-body
Browse files Browse the repository at this point in the history
  • Loading branch information
zhongdalu-trechina authored May 6, 2023
2 parents e04ead0 + 15cedd4 commit b6e36b0
Show file tree
Hide file tree
Showing 21 changed files with 109 additions and 54 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2015-2021 Jeevanandam M., https://myjeeva.com <jeeva@myjeeva.com>
Copyright (c) 2015-2023 Jeevanandam M., https://myjeeva.com <jeeva@myjeeva.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@

#### Supported Go Versions

Recommended to use `go1.16` and above.

Initially Resty started supporting `go modules` since `v1.10.0` release.

Starting Resty v2 and higher versions, it fully embraces [go modules](https://github.com/golang/go/wiki/Modules) package release. It requires a Go version capable of understanding `/vN` suffixed imports:
Expand Down
12 changes: 6 additions & 6 deletions client.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

Expand Down Expand Up @@ -792,7 +792,7 @@ func (c *Client) SetRetryResetReaders(b bool) *Client {
//
// Note: This method overwrites existing `TLSClientConfig`.
func (c *Client) SetTLSClientConfig(config *tls.Config) *Client {
transport, err := c.transport()
transport, err := c.Transport()
if err != nil {
c.log.Errorf("%v", err)
return c
Expand All @@ -809,7 +809,7 @@ func (c *Client) SetTLSClientConfig(config *tls.Config) *Client {
//
// Refer to godoc `http.ProxyFromEnvironment`.
func (c *Client) SetProxy(proxyURL string) *Client {
transport, err := c.transport()
transport, err := c.Transport()
if err != nil {
c.log.Errorf("%v", err)
return c
Expand All @@ -830,7 +830,7 @@ func (c *Client) SetProxy(proxyURL string) *Client {
//
// client.RemoveProxy()
func (c *Client) RemoveProxy() *Client {
transport, err := c.transport()
transport, err := c.Transport()
if err != nil {
c.log.Errorf("%v", err)
return c
Expand Down Expand Up @@ -1140,7 +1140,7 @@ func (c *Client) execute(req *Request) (*Response, error) {

// getting TLS client config if not exists then create one
func (c *Client) tlsConfig() (*tls.Config, error) {
transport, err := c.transport()
transport, err := c.Transport()
if err != nil {
return nil, err
}
Expand All @@ -1152,7 +1152,7 @@ func (c *Client) tlsConfig() (*tls.Config, error) {

// Transport method returns `*http.Transport` currently in use or error
// in case currently used `transport` is not a `*http.Transport`.
func (c *Client) transport() (*http.Transport, error) {
func (c *Client) Transport() (*http.Transport, error) {
if transport, ok := c.httpClient.Transport.(*http.Transport); ok {
return transport, nil
}
Expand Down
31 changes: 17 additions & 14 deletions client_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

Expand Down Expand Up @@ -133,6 +133,7 @@ func TestClientDigestErrors(t *testing.T) {
{mutateConf: func(c *digestServerConfig) { c.charset = "utf-16" }, expect: ErrDigestCharset},
{mutateConf: func(c *digestServerConfig) { c.uri = "/bad" }, expect: ErrDigestBadChallenge},
{mutateConf: func(c *digestServerConfig) { c.uri = "/unknown_param" }, expect: ErrDigestBadChallenge},
{mutateConf: func(c *digestServerConfig) { c.uri = "/missing_value" }, expect: ErrDigestBadChallenge},
{mutateConf: func(c *digestServerConfig) { c.uri = "/no_challenge" }, expect: ErrDigestBadChallenge},
{mutateConf: func(c *digestServerConfig) { c.uri = "/status_500" }, expect: nil},
}
Expand Down Expand Up @@ -180,13 +181,13 @@ func TestClientRedirectPolicy(t *testing.T) {
c := dc().SetRedirectPolicy(FlexibleRedirectPolicy(20))
_, err := c.R().Get(ts.URL + "/redirect-1")

assertEqual(t, true, ("Get /redirect-21: stopped after 20 redirects" == err.Error() ||
"Get \"/redirect-21\": stopped after 20 redirects" == err.Error()))
assertEqual(t, true, (err.Error() == "Get /redirect-21: stopped after 20 redirects" ||
err.Error() == "Get \"/redirect-21\": stopped after 20 redirects"))

c.SetRedirectPolicy(NoRedirectPolicy())
_, err = c.R().Get(ts.URL + "/redirect-1")
assertEqual(t, true, ("Get /redirect-2: auto redirect is disabled" == err.Error() ||
"Get \"/redirect-2\": auto redirect is disabled" == err.Error()))
assertEqual(t, true, (err.Error() == "Get /redirect-2: auto redirect is disabled" ||
err.Error() == "Get \"/redirect-2\": auto redirect is disabled"))
}

func TestClientTimeout(t *testing.T) {
Expand Down Expand Up @@ -248,7 +249,7 @@ func TestClientSetCertificates(t *testing.T) {
client := dc()
client.SetCertificates(tls.Certificate{})

transport, err := client.transport()
transport, err := client.Transport()

assertNil(t, err)
assertEqual(t, 1, len(transport.TLSClientConfig.Certificates))
Expand All @@ -258,7 +259,7 @@ func TestClientSetRootCertificate(t *testing.T) {
client := dc()
client.SetRootCertificate(filepath.Join(getTestDataPath(), "sample-root.pem"))

transport, err := client.transport()
transport, err := client.Transport()

assertNil(t, err)
assertNotNil(t, transport.TLSClientConfig.RootCAs)
Expand All @@ -268,7 +269,7 @@ func TestClientSetRootCertificateNotExists(t *testing.T) {
client := dc()
client.SetRootCertificate(filepath.Join(getTestDataPath(), "not-exists-sample-root.pem"))

transport, err := client.transport()
transport, err := client.Transport()

assertNil(t, err)
assertNil(t, transport.TLSClientConfig)
Expand All @@ -281,7 +282,7 @@ func TestClientSetRootCertificateFromString(t *testing.T) {

client.SetRootCertificateFromString(string(rootPemData))

transport, err := client.transport()
transport, err := client.Transport()

assertNil(t, err)
assertNotNil(t, transport.TLSClientConfig.RootCAs)
Expand All @@ -295,7 +296,7 @@ func TestClientSetRootCertificateFromStringErrorTls(t *testing.T) {
assertNil(t, err)
rt := &CustomRoundTripper{}
client.SetTransport(rt)
transport, err := client.transport()
transport, err := client.Transport()

client.SetRootCertificateFromString(string(rootPemData))

Expand Down Expand Up @@ -333,7 +334,9 @@ func TestClientSetHeaderVerbatim(t *testing.T) {
SetHeaderVerbatim("header-lowercase", "value_lowercase").
SetHeader("header-lowercase", "value_standard")

assertEqual(t, "value_lowercase", strings.Join(c.Header["header-lowercase"], "")) //nolint
//lint:ignore SA1008 valid one, so ignore this!
unConventionHdrValue := strings.Join(c.Header["header-lowercase"], "")
assertEqual(t, "value_lowercase", unConventionHdrValue)
assertEqual(t, "value_standard", c.Header.Get("Header-Lowercase"))
}

Expand All @@ -349,7 +352,7 @@ func TestClientSetTransport(t *testing.T) {
},
}
client.SetTransport(transport)
transportInUse, err := client.transport()
transportInUse, err := client.Transport()

assertNil(t, err)
assertEqual(t, true, transport == transportInUse)
Expand Down Expand Up @@ -448,7 +451,7 @@ func TestClientOptions(t *testing.T) {
}

client.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
transport, transportErr := client.transport()
transport, transportErr := client.Transport()

assertNil(t, transportErr)
assertEqual(t, true, transport.TLSClientConfig.InsecureSkipVerify)
Expand Down Expand Up @@ -562,7 +565,7 @@ func TestClientRoundTripper(t *testing.T) {
rt := &CustomRoundTripper{}
c.SetTransport(rt)

ct, err := c.transport()
ct, err := c.Transport()
assertNotNil(t, err)
assertNil(t, ct)
assertEqual(t, "current transport is not an *http.Transport instance", err.Error())
Expand Down
2 changes: 1 addition & 1 deletion context_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com)
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com)
// 2016 Andrew Grigorev (https://github.com/ei-grad)
// All rights reserved.
// resty source code and usage is governed by a MIT style
Expand Down
9 changes: 9 additions & 0 deletions digest.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com)
// 2023 Segev Dagan (https://github.com/segevda)
// All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

package resty

import (
Expand Down Expand Up @@ -121,6 +127,9 @@ func parseChallenge(input string) (*challenge, error) {
var r []string
for i := range sl {
r = strings.SplitN(sl[i], "=", 2)
if len(r) != 2 {
return nil, ErrDigestBadChallenge
}
switch r[0] {
case "realm":
c.realm = strings.Trim(r[1], qs)
Expand Down
2 changes: 1 addition & 1 deletion example_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 Jeevanandam M. (jeeva@myjeeva.com), All rights reserved.
// Copyright (c) 2015-2023 Jeevanandam M. (jeeva@myjeeva.com), All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

Expand Down
2 changes: 1 addition & 1 deletion middleware.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

Expand Down
8 changes: 6 additions & 2 deletions redirect.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

Expand All @@ -12,6 +12,10 @@ import (
"strings"
)

var (
ErrAutoRedirectDisabled = errors.New("auto redirect is disabled")
)

type (
// RedirectPolicy to regulate the redirects in the resty client.
// Objects implementing the RedirectPolicy interface can be registered as
Expand All @@ -37,7 +41,7 @@ func (f RedirectPolicyFunc) Apply(req *http.Request, via []*http.Request) error
// resty.SetRedirectPolicy(NoRedirectPolicy())
func NoRedirectPolicy() RedirectPolicy {
return RedirectPolicyFunc(func(req *http.Request, via []*http.Request) error {
return errors.New("auto redirect is disabled")
return ErrAutoRedirectDisabled
})
}

Expand Down
19 changes: 17 additions & 2 deletions request.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

Expand Down Expand Up @@ -930,7 +930,7 @@ func (r *Request) fmtBodyString(sl int64) (body string) {
contentType := r.Header.Get(hdrContentTypeKey)
kind := kindOf(r.Body)
if canJSONMarshal(contentType, kind) {
prtBodyBytes, err = json.MarshalIndent(&r.Body, "", " ")
prtBodyBytes, err = noescapeJSONMarshalIndent(&r.Body)
} else if IsXMLType(contentType) && (kind == reflect.Struct) {
prtBodyBytes, err = xml.MarshalIndent(&r.Body, "", " ")
} else if b, ok := r.Body.(string); ok {
Expand Down Expand Up @@ -992,3 +992,18 @@ var noescapeJSONMarshal = func(v interface{}) (*bytes.Buffer, error) {

return buf, nil
}

var noescapeJSONMarshalIndent = func(v interface{}) ([]byte, error) {
buf := acquireBuffer()
defer releaseBuffer(buf)

encoder := json.NewEncoder(buf)
encoder.SetEscapeHTML(false)
encoder.SetIndent("", " ")

if err := encoder.Encode(v); err != nil {
return nil, err
}

return buf.Bytes(), nil
}
11 changes: 6 additions & 5 deletions request_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

Expand Down Expand Up @@ -1122,8 +1122,8 @@ func TestHTTPAutoRedirectUpTo10(t *testing.T) {

_, err := dc().R().Get(ts.URL + "/redirect-1")

assertEqual(t, true, ("Get /redirect-11: stopped after 10 redirects" == err.Error() ||
"Get \"/redirect-11\": stopped after 10 redirects" == err.Error()))
assertEqual(t, true, (err.Error() == "Get /redirect-11: stopped after 10 redirects" ||
err.Error() == "Get \"/redirect-11\": stopped after 10 redirects"))
}

func TestHostCheckRedirectPolicy(t *testing.T) {
Expand Down Expand Up @@ -1252,7 +1252,7 @@ func TestRawFileUploadByBody(t *testing.T) {
func TestProxySetting(t *testing.T) {
c := dc()

transport, err := c.transport()
transport, err := c.Transport()

assertNil(t, err)

Expand Down Expand Up @@ -1464,7 +1464,8 @@ func TestSetHeaderVerbatim(t *testing.T) {
SetHeaderVerbatim("header-lowercase", "value_lowercase").
SetHeader("header-lowercase", "value_standard")

assertEqual(t, "value_lowercase", strings.Join(r.Header["header-lowercase"], "")) //nolint
//lint:ignore SA1008 valid one ignore this!
assertEqual(t, "value_lowercase", strings.Join(r.Header["header-lowercase"], ""))
assertEqual(t, "value_standard", r.Header.Get("Header-Lowercase"))
}

Expand Down
2 changes: 1 addition & 1 deletion response.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

Expand Down
2 changes: 1 addition & 1 deletion resty.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

Expand Down
22 changes: 13 additions & 9 deletions resty_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

Expand Down Expand Up @@ -645,22 +645,27 @@ func createDigestServer(t *testing.T, conf *digestServerConfig) *httptest.Server
if conf == nil {
conf = defaultDigestServerConf()
}

setWWWAuthHeader := func(w http.ResponseWriter, v string) {
w.Header().Set("WWW-Authenticate", v)
w.WriteHeader(http.StatusUnauthorized)
}
ts := createTestServer(func(w http.ResponseWriter, r *http.Request) {
t.Logf("Method: %v", r.Method)
t.Logf("Path: %v", r.URL.Path)

switch r.URL.Path {
case "/bad":
w.Header().Set("WWW-Authenticate", "Bad Challenge")
w.WriteHeader(http.StatusUnauthorized)
setWWWAuthHeader(w, "Bad Challenge")
return
case "/unknown_param":
w.Header().Set("WWW-Authenticate", "Digest unknown_param=true")
w.WriteHeader(http.StatusUnauthorized)
setWWWAuthHeader(w, "Digest unknown_param=true")
return
case "/missing_value":
setWWWAuthHeader(w, `Digest realm="hello", domain`)
return
case "/no_challenge":
w.Header().Set("WWW-Authenticate", "")
w.WriteHeader(http.StatusUnauthorized)
setWWWAuthHeader(w, "")
return
case "/status_500":
w.WriteHeader(http.StatusInternalServerError)
Expand All @@ -670,10 +675,9 @@ func createDigestServer(t *testing.T, conf *digestServerConfig) *httptest.Server
w.Header().Set(hdrContentTypeKey, "application/json; charset=utf-8")

if !authorizationHeaderValid(t, r, conf) {
w.Header().Set("WWW-Authenticate",
setWWWAuthHeader(w,
fmt.Sprintf(`Digest realm="%s", domain="%s", qop="%s", algorithm=%s, nonce="%s", opaque="%s", userhash=true, charset=%s, stale=FALSE`,
conf.realm, conf.uri, conf.qop, conf.algo, conf.nonce, conf.opaque, conf.charset))
w.WriteHeader(http.StatusUnauthorized)
_, _ = w.Write([]byte(`{ "id": "unauthorized", "message": "Invalid credentials" }`))
} else {
w.WriteHeader(http.StatusOK)
Expand Down
5 changes: 4 additions & 1 deletion retry.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

Expand Down Expand Up @@ -209,6 +209,9 @@ func jitterBackoff(min, max time.Duration, attempt int) time.Duration {

temp := math.Min(capLevel, base*math.Exp2(float64(attempt)))
ri := time.Duration(temp / 2)
if ri == 0 {
ri = time.Nanosecond
}
result := randDuration(ri)

if result < min {
Expand Down
Loading

0 comments on commit b6e36b0

Please sign in to comment.