--- /dev/null
+package api
+
+import (
+ "fmt"
+ "reflect"
+ "strconv"
+
+ "github.com/gin-gonic/gin"
+
+ "github.com/vapor/errors"
+)
+
+const (
+ defaultSatrtStr = "0"
+ defaultLimitStr = "10"
+ maxPageLimit = 1000
+)
+
+var (
+ errParsePaginationStart = fmt.Errorf("parse pagination start")
+ errParsePaginationLimit = fmt.Errorf("parse pagination limit")
+)
+
+type PaginationQuery struct {
+ Start uint64 `json:"start"`
+ Limit uint64 `json:"limit"`
+}
+
+// parsePagination request meets the standard on https://developer.atlassian.com/server/confluence/pagination-in-the-rest-api/
+func parsePagination(c *gin.Context) (*PaginationQuery, error) {
+ startStr := c.DefaultQuery("start", defaultSatrtStr)
+ limitStr := c.DefaultQuery("limit", defaultLimitStr)
+
+ start, err := strconv.ParseUint(startStr, 10, 64)
+ if err != nil {
+ return nil, errors.Wrap(err, errParsePaginationStart)
+ }
+
+ limit, err := strconv.ParseUint(limitStr, 10, 64)
+ if err != nil {
+ return nil, errors.Wrap(err, errParsePaginationLimit)
+ }
+
+ if limit > maxPageLimit {
+ limit = maxPageLimit
+ }
+
+ return &PaginationQuery{
+ Start: start,
+ Limit: limit,
+ }, nil
+}
+
+type PaginationInfo struct {
+ Start uint64
+ Limit uint64
+ HasNext bool
+}
+
+func processPaginationIfPresent(fun handlerFun, args []interface{}, result []interface{}, context *gin.Context) bool {
+ ft := reflect.TypeOf(fun)
+ if ft.NumIn() != 3 {
+ return false
+ }
+
+ list := result[0]
+ size := reflect.ValueOf(list).Len()
+ query := args[2].(*PaginationQuery)
+
+ paginationInfo := &PaginationInfo{Start: query.Start, Limit: query.Limit, HasNext: size == int(query.Limit)}
+ respondSuccessPaginationResp(context, list, paginationInfo)
+ return true
+}