From f13ee9adafa9b623ef08b91bc9a4b474fc185731 Mon Sep 17 00:00:00 2001 From: Sergey Vilgelm Date: Mon, 25 Sep 2023 09:45:56 -0700 Subject: [PATCH] improve the performance of applying the query parameters * improve the loging by adding the query parameters from the request first, then adding the parameters from the client and skip if already exists * additional unit tests for the query parameters ```shell % go test -benchmem -bench=. -run=^Benchmark goos: darwin goarch: amd64 pkg: github.com/go-resty/resty/v2 cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz Benchmark_parseRequestURL_QueryParams-16 800851 1490 ns/op 400 B/op 9 allocs/op PASS ok github.com/go-resty/resty/v2 2.473s ``` --- middleware.go | 41 ++++++++++++++++++++--------------------- middleware_test.go | 21 ++++++++++++++++++++- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/middleware.go b/middleware.go index a3ac21d4..445f7360 100644 --- a/middleware.go +++ b/middleware.go @@ -134,32 +134,31 @@ func parseRequestURL(c *Client, r *Request) error { } // Adding Query Param - query := make(url.Values) - for k, v := range c.QueryParam { - for _, iv := range v { - query.Add(k, iv) + if l := len(c.QueryParam) + len(r.QueryParam); l > 0 { + query := make(url.Values, l) + for k, v := range r.QueryParam { + query[k] = v[:] } - } - for k, v := range r.QueryParam { - // remove query param from client level by key - // since overrides happens for that key in the request - query.Del(k) + for k, v := range c.QueryParam { + // skip query parameter if it was set from request + if _, ok := query[k]; ok { + continue + } - for _, iv := range v { - query.Add(k, iv) + query[k] = v[:] } - } - // GitHub #123 Preserve query string order partially. - // Since not feasible in `SetQuery*` resty methods, because - // standard package `url.Encode(...)` sorts the query params - // alphabetically - if len(query) > 0 { - if IsStringEmpty(reqURL.RawQuery) { - reqURL.RawQuery = query.Encode() - } else { - reqURL.RawQuery = reqURL.RawQuery + "&" + query.Encode() + // GitHub #123 Preserve query string order partially. + // Since not feasible in `SetQuery*` resty methods, because + // standard package `url.Encode(...)` sorts the query params + // alphabetically + if len(query) > 0 { + if IsStringEmpty(reqURL.RawQuery) { + reqURL.RawQuery = query.Encode() + } else { + reqURL.RawQuery = reqURL.RawQuery + "&" + query.Encode() + } } } diff --git a/middleware_test.go b/middleware_test.go index b5061ee7..3520d3d8 100644 --- a/middleware_test.go +++ b/middleware_test.go @@ -200,13 +200,32 @@ func Test_parseRequestURL(t *testing.T) { "foo": "1", // ignored, because of the "foo" parameter in request "bar": "2", }) - c.SetQueryParams(map[string]string{ + r.SetQueryParams(map[string]string{ "foo": "3", }) r.URL = "https://example.com/" }, expectedURL: "https://example.com/?foo=3&bar=2", }, + { + name: "adding query parameters by request to URL with existent", + init: func(c *Client, r *Request) { + r.SetQueryParams(map[string]string{ + "bar": "2", + }) + r.URL = "https://example.com/?foo=1" + }, + expectedURL: "https://example.com/?foo=1&bar=2", + }, + { + name: "adding query parameters by request with multiple values", + init: func(c *Client, r *Request) { + r.QueryParam.Add("foo", "1") + r.QueryParam.Add("foo", "2") + r.URL = "https://example.com/" + }, + expectedURL: "https://example.com/?foo=1&foo=2", + }, } { t.Run(tt.name, func(t *testing.T) { c := New()