Skip to content

Commit 4aea34e

Browse files
authored
Merge pull request #392 from IBM-Cloud/feat/validate-pagination-cache-url
feat: added validation method for pagination cache url
2 parents a3f3f5d + b67322d commit 4aea34e

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

bluemix/configuration/config_helpers/helpers.go

+44
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
package config_helpers
33

44
import (
5+
"encoding/base64"
6+
gourl "net/url"
57
"os"
68
"path/filepath"
79
"runtime"
@@ -91,3 +93,45 @@ func UserHomeDir() string {
9193

9294
return os.Getenv("HOME")
9395
}
96+
97+
// IsValidPaginationNextURL will return true if the provided nextURL has the expected queries provided
98+
func IsValidPaginationNextURL(nextURL string, cursorQueryParamName string, expectedQueries gourl.Values) bool {
99+
parsedURL, parseErr := gourl.Parse(nextURL)
100+
// NOTE: ignore handling error(s) since if there error(s)
101+
// we can assume the url is invalid
102+
if parseErr != nil {
103+
return false
104+
}
105+
106+
// retrive encoded cursor
107+
// eg. /api?cursor=<encode_string>
108+
queries := parsedURL.Query()
109+
encodedQuery := queries.Get(cursorQueryParamName)
110+
if encodedQuery == "" {
111+
return false
112+
113+
}
114+
// decode string and parse encoded queries
115+
decodedQuery, decodedErr := base64.RawURLEncoding.DecodeString(encodedQuery)
116+
if decodedErr != nil {
117+
return false
118+
}
119+
queries, parsedErr := gourl.ParseQuery(string(decodedQuery))
120+
if parsedErr != nil {
121+
return false
122+
}
123+
124+
// compare expected queries that should match
125+
// NOTE: assume queries are single value queries.
126+
// if multi-value queries will check the first query
127+
for expectedQuery := range expectedQueries {
128+
paginationQueryValue := queries.Get(expectedQuery)
129+
expectedQueryValue := expectedQueries.Get(expectedQuery)
130+
if paginationQueryValue != expectedQueryValue {
131+
return false
132+
}
133+
134+
}
135+
136+
return true
137+
}

bluemix/configuration/config_helpers/helpers_test.go

+61
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package config_helpers
22

33
import (
4+
"encoding/base64"
45
"io/ioutil"
6+
gourl "net/url"
57
"os"
68
"path/filepath"
79
"strings"
@@ -103,3 +105,62 @@ func TestConfigDir_IbmCloudConfigHomeSet_Exists(t *testing.T) {
103105
os.Setenv("IBMCLOUD_CONFIG_HOME", userHome)
104106
assert.Equal(userHome, ConfigDir())
105107
}
108+
109+
func TestIsValidPaginationNextURL(t *testing.T) {
110+
assert := assert.New(t)
111+
112+
testCases := []struct {
113+
name string
114+
nextURL string
115+
encodedQueryParam string
116+
expectedQueries gourl.Values
117+
isValid bool
118+
}{
119+
{
120+
name: "return true for matching expected queries in pagination url",
121+
nextURL: "/api/example?cursor=" + base64.RawURLEncoding.EncodeToString([]byte("limit=100&active=true")),
122+
encodedQueryParam: "cursor",
123+
expectedQueries: gourl.Values{
124+
"limit": []string{"100"},
125+
"active": []string{"true"},
126+
},
127+
isValid: true,
128+
},
129+
{
130+
name: "return true for matching expected queries with extraneous queries in pagination url",
131+
nextURL: "/api/example?cursor=" + base64.RawURLEncoding.EncodeToString([]byte("limit=100&active=true&extra=foo")),
132+
encodedQueryParam: "cursor",
133+
expectedQueries: gourl.Values{
134+
"limit": []string{"100"},
135+
"active": []string{"true"},
136+
},
137+
isValid: true,
138+
},
139+
{
140+
name: "return false for different limit in pagination url",
141+
nextURL: "/api/example?cursor=" + base64.RawURLEncoding.EncodeToString([]byte("limit=200")),
142+
encodedQueryParam: "cursor",
143+
expectedQueries: gourl.Values{
144+
"limit": []string{"100"},
145+
},
146+
isValid: false,
147+
},
148+
{
149+
name: "return false for different query among multiple parameters in the pagination url",
150+
nextURL: "/api/example?cursor=" + base64.RawURLEncoding.EncodeToString([]byte("limit=100&active=true")),
151+
encodedQueryParam: "cursor",
152+
expectedQueries: gourl.Values{
153+
"limit": []string{"100"},
154+
"active": []string{"false"},
155+
},
156+
isValid: false,
157+
},
158+
}
159+
160+
for _, tc := range testCases {
161+
t.Run(tc.name, func(_ *testing.T) {
162+
isValid := IsValidPaginationNextURL(tc.nextURL, tc.encodedQueryParam, tc.expectedQueries)
163+
assert.Equal(tc.isValid, isValid)
164+
})
165+
}
166+
}

0 commit comments

Comments
 (0)