Skip to content

Commit 96f6424

Browse files
authored
Merge pull request #8 from speakeasy-api/feat/non_numeric_pagination
feat: non numeric pagination
2 parents 8edcb0d + 22920de commit 96f6424

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed

cmd/server/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func main() {
3535
r.HandleFunc("/pagination/limitoffset/offset", pagination.HandleLimitOffsetOffset).Methods(http.MethodGet, http.MethodPut)
3636
r.HandleFunc("/pagination/cursor", pagination.HandleCursor).Methods(http.MethodGet, http.MethodPut)
3737
r.HandleFunc("/pagination/url", pagination.HandleURL).Methods(http.MethodGet)
38+
r.HandleFunc("/pagination/cursor_non_numeric", pagination.HandleNonNumericCursor).Methods(http.MethodGet)
3839
r.HandleFunc("/retries", retries.HandleRetries).Methods(http.MethodGet, http.MethodPost)
3940
r.HandleFunc("/retries/after", retries.HandleRetries).Methods(http.MethodGet)
4041
r.HandleFunc("/errors/{status_code}", errors.HandleErrors).Methods(http.MethodGet)

internal/pagination/service.go

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,22 @@ type CursorRequest struct {
1818
Cursor int `json:"cursor"`
1919
}
2020

21+
type NonNumericCursorRequest struct {
22+
Cursor string `json:"cursor"`
23+
}
24+
2125
type PaginationResponse struct {
22-
NumPages int `json:"numPages"`
23-
ResultArray []int `json:"resultArray"`
24-
Next *string `json:"next,omitempty"`
26+
NumPages int `json:"numPages"`
27+
ResultArray []interface{} `json:"resultArray"`
28+
Next *string `json:"next,omitempty"`
29+
}
30+
31+
// Insecure reversable hashing for string cursors
32+
func hash(s string) (int, error) {
33+
return strconv.Atoi(s)
34+
}
35+
func unhash(h int) string {
36+
return strconv.Itoa(h)
2537
}
2638

2739
const total = 20
@@ -45,7 +57,7 @@ func HandleLimitOffsetPage(w http.ResponseWriter, r *http.Request) {
4557

4658
res := PaginationResponse{
4759
NumPages: int(math.Ceil(float64(total) / float64(limit))),
48-
ResultArray: make([]int, 0),
60+
ResultArray: make([]interface{}, 0),
4961
}
5062

5163
for i := start; i < total && len(res.ResultArray) < limit; i++ {
@@ -77,7 +89,7 @@ func HandleLimitOffsetOffset(w http.ResponseWriter, r *http.Request) {
7789

7890
res := PaginationResponse{
7991
NumPages: int(math.Ceil(float64(total) / float64(limit))),
80-
ResultArray: make([]int, 0),
92+
ResultArray: make([]interface{}, 0),
8193
}
8294

8395
for i := offset; i < total && len(res.ResultArray) < limit; i++ {
@@ -104,7 +116,7 @@ func HandleCursor(w http.ResponseWriter, r *http.Request) {
104116

105117
res := PaginationResponse{
106118
NumPages: 0,
107-
ResultArray: make([]int, 0),
119+
ResultArray: make([]interface{}, 0),
108120
}
109121

110122
for i := cursor + 1; i < total && len(res.ResultArray) < 15; i++ {
@@ -134,7 +146,7 @@ func HandleURL(w http.ResponseWriter, r *http.Request) {
134146

135147
res := PaginationResponse{
136148
NumPages: 0,
137-
ResultArray: make([]int, 0),
149+
ResultArray: make([]interface{}, 0),
138150
}
139151

140152
if attempts > 1 {
@@ -160,6 +172,31 @@ func HandleURL(w http.ResponseWriter, r *http.Request) {
160172
}
161173
}
162174

175+
func HandleNonNumericCursor(w http.ResponseWriter, r *http.Request) {
176+
queryCursor := r.FormValue("cursor")
177+
var pagination NonNumericCursorRequest
178+
hasBody := true
179+
if err := json.NewDecoder(r.Body).Decode(&pagination); err != nil {
180+
hasBody = false
181+
}
182+
cursor := getNonNumericValue(queryCursor, hasBody, pagination.Cursor)
183+
184+
res := PaginationResponse{
185+
NumPages: 0,
186+
ResultArray: make([]interface{}, 0),
187+
}
188+
var cursorI, _ = hash(cursor)
189+
for i := cursorI + 1; i < total && len(res.ResultArray) < 15; i++ {
190+
res.ResultArray = append(res.ResultArray, unhash(i))
191+
}
192+
193+
w.Header().Set("Content-Type", "application/json")
194+
err := json.NewEncoder(w).Encode(res)
195+
if err != nil {
196+
w.WriteHeader(500)
197+
}
198+
}
199+
163200
func getValue(queryValue string, hasBody bool, paginationValue int) int {
164201
if hasBody {
165202
return paginationValue
@@ -171,3 +208,15 @@ func getValue(queryValue string, hasBody bool, paginationValue int) int {
171208
return value
172209
}
173210
}
211+
212+
func getNonNumericValue(queryValue string, hasBody bool, paginationValue string) string {
213+
if hasBody {
214+
return paginationValue
215+
} else {
216+
if queryValue == "" {
217+
return "-1"
218+
} else {
219+
return queryValue
220+
}
221+
}
222+
}

0 commit comments

Comments
 (0)