blob: 75a925490a2ad93e0715abc3bed1607382d5ca1b [file] [log] [blame] [edit]
package response
import (
"net/url"
"strconv"
)
// PaginationMeta is a structure included in responses for pagination.
type PaginationMeta struct {
Limit int `json:"limit"`
CurrentOffset int `json:"current_offset"`
NextOffset *int `json:"next_offset,omitempty"`
PrevOffset *int `json:"prev_offset,omitempty"`
NextURL string `json:"next_url,omitempty"`
PrevURL string `json:"prev_url,omitempty"`
}
// NewPaginationMeta populates pagination meta data from result parameters
func NewPaginationMeta(offset, limit int, hasMore bool, currentURL string) PaginationMeta {
pm := PaginationMeta{
Limit: limit,
CurrentOffset: offset,
}
// Calculate next/prev offsets, leave nil if not valid pages
nextOffset := offset + limit
if hasMore {
pm.NextOffset = &nextOffset
}
prevOffset := offset - limit
if prevOffset < 0 {
prevOffset = 0
}
if prevOffset < offset {
pm.PrevOffset = &prevOffset
}
// If URL format provided, populate URLs. Intentionally swallow URL errors for now, API should
// catch missing URLs if we call with bad URL arg (and we care about them being present).
if currentURL != "" && pm.NextOffset != nil {
pm.NextURL, _ = setQueryParam(currentURL, "offset", *pm.NextOffset, 0)
}
if currentURL != "" && pm.PrevOffset != nil {
pm.PrevURL, _ = setQueryParam(currentURL, "offset", *pm.PrevOffset, 0)
}
return pm
}
func setQueryParam(baseURL, key string, val, defaultVal int) (string, error) {
u, err := url.Parse(baseURL)
if err != nil {
return "", err
}
q := u.Query()
if val == defaultVal {
// elide param if it's the default value
q.Del(key)
} else {
q.Set(key, strconv.Itoa(val))
}
u.RawQuery = q.Encode()
return u.String(), nil
}