Skip to content

Commit

Permalink
Merge pull request #8 from speakeasy-api/feat/non_numeric_pagination
Browse files Browse the repository at this point in the history
feat: non numeric pagination
  • Loading branch information
idbentley authored Feb 28, 2024
2 parents 8edcb0d + 22920de commit 96f6424
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 7 deletions.
1 change: 1 addition & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func main() {
r.HandleFunc("/pagination/limitoffset/offset", pagination.HandleLimitOffsetOffset).Methods(http.MethodGet, http.MethodPut)
r.HandleFunc("/pagination/cursor", pagination.HandleCursor).Methods(http.MethodGet, http.MethodPut)
r.HandleFunc("/pagination/url", pagination.HandleURL).Methods(http.MethodGet)
r.HandleFunc("/pagination/cursor_non_numeric", pagination.HandleNonNumericCursor).Methods(http.MethodGet)
r.HandleFunc("/retries", retries.HandleRetries).Methods(http.MethodGet, http.MethodPost)
r.HandleFunc("/retries/after", retries.HandleRetries).Methods(http.MethodGet)
r.HandleFunc("/errors/{status_code}", errors.HandleErrors).Methods(http.MethodGet)
Expand Down
63 changes: 56 additions & 7 deletions internal/pagination/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,22 @@ type CursorRequest struct {
Cursor int `json:"cursor"`
}

type NonNumericCursorRequest struct {
Cursor string `json:"cursor"`
}

type PaginationResponse struct {
NumPages int `json:"numPages"`
ResultArray []int `json:"resultArray"`
Next *string `json:"next,omitempty"`
NumPages int `json:"numPages"`
ResultArray []interface{} `json:"resultArray"`
Next *string `json:"next,omitempty"`
}

// Insecure reversable hashing for string cursors
func hash(s string) (int, error) {
return strconv.Atoi(s)
}
func unhash(h int) string {
return strconv.Itoa(h)
}

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

res := PaginationResponse{
NumPages: int(math.Ceil(float64(total) / float64(limit))),
ResultArray: make([]int, 0),
ResultArray: make([]interface{}, 0),
}

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

res := PaginationResponse{
NumPages: int(math.Ceil(float64(total) / float64(limit))),
ResultArray: make([]int, 0),
ResultArray: make([]interface{}, 0),
}

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

res := PaginationResponse{
NumPages: 0,
ResultArray: make([]int, 0),
ResultArray: make([]interface{}, 0),
}

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

res := PaginationResponse{
NumPages: 0,
ResultArray: make([]int, 0),
ResultArray: make([]interface{}, 0),
}

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

func HandleNonNumericCursor(w http.ResponseWriter, r *http.Request) {
queryCursor := r.FormValue("cursor")
var pagination NonNumericCursorRequest
hasBody := true
if err := json.NewDecoder(r.Body).Decode(&pagination); err != nil {
hasBody = false
}
cursor := getNonNumericValue(queryCursor, hasBody, pagination.Cursor)

res := PaginationResponse{
NumPages: 0,
ResultArray: make([]interface{}, 0),
}
var cursorI, _ = hash(cursor)
for i := cursorI + 1; i < total && len(res.ResultArray) < 15; i++ {
res.ResultArray = append(res.ResultArray, unhash(i))
}

w.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(w).Encode(res)
if err != nil {
w.WriteHeader(500)
}
}

func getValue(queryValue string, hasBody bool, paginationValue int) int {
if hasBody {
return paginationValue
Expand All @@ -171,3 +208,15 @@ func getValue(queryValue string, hasBody bool, paginationValue int) int {
return value
}
}

func getNonNumericValue(queryValue string, hasBody bool, paginationValue string) string {
if hasBody {
return paginationValue
} else {
if queryValue == "" {
return "-1"
} else {
return queryValue
}
}
}

0 comments on commit 96f6424

Please sign in to comment.