Skip to content

Commit

Permalink
23/07/23: Add go-resty#664
Browse files Browse the repository at this point in the history
  • Loading branch information
3JoB committed Jul 23, 2023
1 parent d5cb159 commit 0593095
Show file tree
Hide file tree
Showing 5 changed files with 262 additions and 43 deletions.
83 changes: 70 additions & 13 deletions client.go
Expand Up @@ -106,27 +106,29 @@ type (
// Resty also provides an options to override most of the client settings
// at request level.
type Client struct {
BaseURL string
HostURL string // Deprecated: use BaseURL instead. To be removed in v3.0.0 release.
QueryParam url.Values
FormData url.Values
PathParams map[string]string
Header http.Header
UserInfo *User
Token string
AuthScheme string
BaseURL string
HostURL string // Deprecated: use BaseURL instead. To be removed in v3.0.0 release.
Token string
AuthScheme string
QueryParam url.Values
FormData url.Values
PathParams map[string]string
RawPathParams map[string]string
Header http.Header
UserInfo *User

Cookies []*http.Cookie
Error reflect.Type
Debug bool
DisableWarn bool
AllowGetMethodPayload bool
RetryResetReaders bool
RetryCount int
RetryWaitTime time.Duration
RetryMaxWaitTime time.Duration
RetryConditions []RetryConditionFunc
RetryHooks []OnRetryFunc
RetryAfter RetryAfterFunc
RetryResetReaders bool
JSONMarshal func(v any) ([]byte, error)
JSONUnmarshal func(data []byte, v any) error
XMLMarshal func(v any) ([]byte, error)
Expand Down Expand Up @@ -473,6 +475,7 @@ func (c *Client) R() *Request {
multipartFiles: []*File{},
multipartFields: []*MultipartField{},
PathParams: map[string]string{},
RawPathParams: map[string]string{},
jsonEscapeHTML: true,
log: c.log,
}
Expand Down Expand Up @@ -996,6 +999,7 @@ func (c *Client) SetDoNotParseResponse(parse bool) *Client {
// Composed URL - /v1/users/sample@sample.com/details
//
// It replaces the value of the key while composing the request URL.
// The value will be escaped using `url.PathEscape` function.
//
// Also it can be overridden at request level Path Params options,
// see `Request.SetPathParam` or `Request.SetPathParams`.
Expand All @@ -1008,15 +1012,17 @@ func (c *Client) SetPathParam(param, value string) *Client {
// Resty client instance.
//
// client.SetPathParams(map[string]string{
// "userId": "sample@sample.com",
// "userId": "sample@sample.com",
// "subAccountId": "100002",
// "path": "groups/developers",
// })
//
// Result:
// URL - /v1/users/{userId}/{subAccountId}/details
// Composed URL - /v1/users/sample@sample.com/100002/details
// URL - /v1/users/{userId}/{subAccountId}/{path}/details
// Composed URL - /v1/users/sample@sample.com/100002/groups%2Fdevelopers/details
//
// It replaces the value of the key while composing the request URL.
// The values will be escaped using `url.PathEscape` function.
//
// Also it can be overridden at request level Path Params options,
// see `Request.SetPathParam` or `Request.SetPathParams`.
Expand All @@ -1027,6 +1033,56 @@ func (c *Client) SetPathParams(params map[string]string) *Client {
return c
}

// SetRawPathParam method sets single URL path key-value pair in the
// Resty client instance.
//
// client.SetPathParam("userId", "sample@sample.com")
//
// Result:
// URL - /v1/users/{userId}/details
// Composed URL - /v1/users/sample@sample.com/details
//
// client.SetPathParam("path", "groups/developers")
//
// Result:
// URL - /v1/users/{userId}/details
// Composed URL - /v1/users/groups%2Fdevelopers/details
//
// It replaces the value of the key while composing the request URL.
// The value will be used as it is and will not be escaped.
//
// Also it can be overridden at request level Path Params options,
// see `Request.SetPathParam` or `Request.SetPathParams`.
func (c *Client) SetRawPathParam(param, value string) *Client {
c.RawPathParams[param] = value
return c
}

// SetRawPathParams method sets multiple URL path key-value pairs at one go in the
// Resty client instance.
//
// client.SetPathParams(map[string]string{
// "userId": "sample@sample.com",
// "subAccountId": "100002",
// "path": "groups/developers",
// })
//
// Result:
// URL - /v1/users/{userId}/{subAccountId}/{path}/details
// Composed URL - /v1/users/sample@sample.com/100002/groups/developers/details
//
// It replaces the value of the key while composing the request URL.
// The values will be used as they are and will not be escaped.
//
// Also it can be overridden at request level Path Params options,
// see `Request.SetPathParam` or `Request.SetPathParams`.
func (c *Client) SetRawPathParams(params map[string]string) *Client {
for p, v := range params {
c.SetRawPathParam(p, v)
}
return c
}

// SetJSONEscapeHTML method is to enable/disable the HTML escape on JSON marshal.
//
// Note: This option only applicable to standard JSON Marshaller.
Expand Down Expand Up @@ -1288,6 +1344,7 @@ func createClient(hc *http.Client) *Client {
RetryWaitTime: defaultWaitTime,
RetryMaxWaitTime: defaultMaxWaitTime,
PathParams: make(map[string]string),
RawPathParams: make(map[string]string),
JSONMarshal: json.Marshal,
JSONUnmarshal: json.Unmarshal,
XMLMarshal: xml.Marshal,
Expand Down
21 changes: 19 additions & 2 deletions middleware.go
Expand Up @@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"io"
"log"
"mime/multipart"
"net/http"
"net/url"
Expand All @@ -17,6 +18,7 @@ import (
"strings"
"time"

"github.com/3JoB/ulib/litefmt"
"github.com/3JoB/unsafeConvert"
"github.com/goccy/go-reflect"
)
Expand All @@ -39,6 +41,18 @@ func parseRequestURL(c *Client, r *Request) error {
}
}

// GitHub #663 Raw Path Params
if len(r.RawPathParams) > 0 {
for p, v := range r.RawPathParams {
r.URL = strings.ReplaceAll(r.URL, "{"+p+"}", v)
}
}
if len(c.RawPathParams) > 0 {
for p, v := range c.RawPathParams {
r.URL = strings.ReplaceAll(r.URL, "{"+p+"}", v)
}
}

// Parsing request URL
reqURL, err := url.Parse(r.URL)
if err != nil {
Expand Down Expand Up @@ -90,7 +104,7 @@ func parseRequestURL(c *Client, r *Request) error {
if IsStringEmpty(reqURL.RawQuery) {
reqURL.RawQuery = query.Encode()
} else {
reqURL.RawQuery = reqURL.RawQuery + "&" + query.Encode()
reqURL.RawQuery = litefmt.Sprint(reqURL.RawQuery, "&", query.Encode())
}
}

Expand Down Expand Up @@ -347,7 +361,10 @@ func parseResponseBody(c *Client, res *Response) (err error) {
}

if res.Request.Error != nil {
err = Unmarshalc(c, ct, res.body, res.Request.Error)
unmarshalErr := Unmarshalc(c, ct, res.body, res.Request.Error)
if unmarshalErr != nil {
log.Printf("[WARN] Cannot unmarshal response body: %s", unmarshalErr)
}
}
}
}
Expand Down
112 changes: 88 additions & 24 deletions request.go
Expand Up @@ -29,22 +29,23 @@ import (
// resty client. Request provides an options to override client level
// settings and also an options for the request composition.
type Request struct {
URL string
Method string
Token string
AuthScheme string
QueryParam url.Values
FormData url.Values
PathParams map[string]string
Header http.Header
Time time.Time
Body any
Result any
Error any
RawRequest *http.Request
SRV *SRVRecord
UserInfo *User
Cookies []*http.Cookie
URL string
Method string
Token string
AuthScheme string
QueryParam url.Values
FormData url.Values
PathParams map[string]string
RawPathParams map[string]string
Header http.Header
Time time.Time
Body any
Result any
Error any
RawRequest *http.Request
SRV *SRVRecord
UserInfo *User
Cookies []*http.Cookie

// Attempt is to represent the request attempt made during a Resty
// request execution flow, including retry count.
Expand Down Expand Up @@ -581,8 +582,17 @@ func (r *Request) SetDoNotParseResponse(parse bool) *Request {
// URL - /v1/users/{userId}/details
// Composed URL - /v1/users/sample@sample.com/details
//
// It replaces the value of the key while composing the request URL. Also you can
// override Path Params value, which was set at client instance level.
// client.R().SetPathParam("path", "groups/developers")
//
// Result:
// URL - /v1/users/{userId}/details
// Composed URL - /v1/users/groups%2Fdevelopers/details
//
// It replaces the value of the key while composing the request URL.
// The values will be escaped using `url.PathEscape` function.
//
// Also you can override Path Params value, which was set at client instance
// level.
func (r *Request) SetPathParam(param, value string) *Request {
r.PathParams[param] = value
return r
Expand All @@ -592,23 +602,77 @@ func (r *Request) SetPathParam(param, value string) *Request {
// Resty current request instance.
//
// client.R().SetPathParams(map[string]string{
// "userId": "sample@sample.com",
// "subAccountId": "100002",
// "userId": "sample@sample.com",
// "subAccountId": "100002",
// "path": "groups/developers",
// })
//
// Result:
// URL - /v1/users/{userId}/{subAccountId}/details
// Composed URL - /v1/users/sample@sample.com/100002/details
// URL - /v1/users/{userId}/{subAccountId}/{path}/details
// Composed URL - /v1/users/sample@sample.com/100002/groups%2Fdevelopers/details
//
// It replaces the value of the key while composing request URL. Also you can
// override Path Params value, which was set at client instance level.
// It replaces the value of the key while composing request URL.
// The value will be used as it is and will not be escaped.
//
// Also you can override Path Params value, which was set at client instance
// level.
func (r *Request) SetPathParams(params map[string]string) *Request {
for p, v := range params {
r.SetPathParam(p, v)
}
return r
}

// SetRawPathParam method sets single URL path key-value pair in the
// Resty current request instance.
//
// client.R().SetPathParam("userId", "sample@sample.com")
//
// Result:
// URL - /v1/users/{userId}/details
// Composed URL - /v1/users/sample@sample.com/details
//
// client.R().SetPathParam("path", "groups/developers")
//
// Result:
// URL - /v1/users/{userId}/details
// Composed URL - /v1/users/groups/developers/details
//
// It replaces the value of the key while composing the request URL.
// The value will be used as it is and will not be escaped.
//
// Also you can override Path Params value, which was set at client instance
// level.
func (r *Request) SetRawPathParam(param, value string) *Request {
r.RawPathParams[param] = value
return r
}

// SetRawPathParams method sets multiple URL path key-value pairs at one go in the
// Resty current request instance.
//
// client.R().SetPathParams(map[string]string{
// "userId": "sample@sample.com",
// "subAccountId": "100002",
// "path": "groups/developers",
// })
//
// Result:
// URL - /v1/users/{userId}/{subAccountId}/{path}/details
// Composed URL - /v1/users/sample@sample.com/100002/groups/developers/details
//
// It replaces the value of the key while composing request URL.
// The values will be used as they are and will not be escaped.
//
// Also you can override Path Params value, which was set at client instance
// level.
func (r *Request) SetRawPathParams(params map[string]string) *Request {
for p, v := range params {
r.SetRawPathParam(p, v)
}
return r
}

// ExpectContentType method allows to provide fallback `Content-Type` for automatic unmarshalling
// when `Content-Type` response header is unavailable.
func (r *Request) ExpectContentType(contentType string) *Request {
Expand Down

0 comments on commit 0593095

Please sign in to comment.