Skip to content

Commit

Permalink
feat: add x-total-count to paginated pages
Browse files Browse the repository at this point in the history
  • Loading branch information
aeneasr committed Nov 10, 2021
1 parent 39e0eb6 commit b633ec3
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 235 deletions.
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ require (
github.com/ory/kratos-client-go v0.6.3-alpha.1
github.com/ory/mail/v3 v3.0.0
github.com/ory/nosurf v1.2.6
github.com/ory/x v0.0.300
github.com/ory/x v0.0.310
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
github.com/pkg/errors v0.9.1
github.com/pquerna/otp v1.3.0
Expand All @@ -91,7 +91,6 @@ require (
github.com/tidwall/sjson v1.2.2
github.com/urfave/negroni v1.0.0
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
golang.org/x/mod v0.5.1 // indirect
golang.org/x/net v0.0.0-20211020060615-d418f374d309
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1586,8 +1586,8 @@ github.com/ory/x v0.0.205/go.mod h1:A1s4iwmFIppRXZLF3J9GGWeY/HpREVm0Dk5z/787iek=
github.com/ory/x v0.0.250/go.mod h1:jUJaVptu+geeqlb9SyQCogTKj5ztSDIF6APkhbKtwLc=
github.com/ory/x v0.0.272/go.mod h1:1TTPgJGQutrhI2OnwdrTIHE9ITSf4MpzXFzA/ncTGRc=
github.com/ory/x v0.0.288/go.mod h1:APpShLyJcVzKw1kTgrHI+j/L9YM+8BRjHlcYObc7C1U=
github.com/ory/x v0.0.300 h1:uFkjn6+pB55tnWg1KGaeVewBRULL/cQTrpSQGbz3rbg=
github.com/ory/x v0.0.300/go.mod h1:CDs8F4TtG/A+F9FfBR40G7u/gA3Rg1+NcvkLlxN+H+Q=
github.com/ory/x v0.0.310 h1:Lk4g7PKm3PWfV29A+WEjn8y3MNG35ucG0D9mclSIQOo=
github.com/ory/x v0.0.310/go.mod h1:CDs8F4TtG/A+F9FfBR40G7u/gA3Rg1+NcvkLlxN+H+Q=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/parnurzeal/gorequest v0.2.15/go.mod h1:3Kh2QUMJoqw3icWAecsyzkpY7UzRfDhbRdTjtNwNiUE=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
Expand Down
3 changes: 2 additions & 1 deletion identity/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"net/http"
"time"

"github.com/ory/kratos/x"

"github.com/ory/kratos/cipher"

"github.com/ory/herodot"
Expand All @@ -18,7 +20,6 @@ import (
"github.com/ory/x/urlx"

"github.com/ory/kratos/driver/config"
"github.com/ory/kratos/x"
)

const RouteCollection = "/identities"
Expand Down
106 changes: 9 additions & 97 deletions x/pagination.go
Original file line number Diff line number Diff line change
@@ -1,113 +1,25 @@
package x

import (
"fmt"
"net/http"
"net/url"
"strconv"
"strings"

"github.com/ory/x/pagination/pagepagination"
)

const paginationMaxItems = 1000
const paginationDefaultItems = 250

// ParsePagination parses limit and page from *http.Request with given limits and defaults.
func ParsePagination(r *http.Request) (page, itemsPerPage int) {
if offsetParam := r.URL.Query().Get("page"); offsetParam == "" {
page = 0
} else {
if offset, err := strconv.ParseInt(offsetParam, 10, 0); err != nil {
page = 0
} else {
page = int(offset)
}
}

if limitParam := r.URL.Query().Get("per_page"); limitParam == "" {
itemsPerPage = paginationDefaultItems
} else {
if limit, err := strconv.ParseInt(limitParam, 10, 0); err != nil {
itemsPerPage = paginationDefaultItems
} else {
itemsPerPage = int(limit)
}
}

if itemsPerPage > paginationMaxItems {
itemsPerPage = paginationMaxItems
}

if itemsPerPage < 1 {
itemsPerPage = 1
}

if page < 0 {
page = 0
}

return
var paginator = &pagepagination.PagePaginator{
MaxItems: paginationMaxItems,
DefaultItems: paginationDefaultItems,
}

func header(u *url.URL, rel string, limit, page int64) string {
q := u.Query()
q.Set("per_page", fmt.Sprintf("%d", limit))
q.Set("page", fmt.Sprintf("%d", page/limit))
u.RawQuery = q.Encode()
return fmt.Sprintf("<%s>; rel=\"%s\"", u.String(), rel)
// ParsePagination parses limit and page from *http.Request with given limits and defaults.
func ParsePagination(r *http.Request) (page, itemsPerPage int) {
return paginator.ParsePagination(r)
}

func PaginationHeader(w http.ResponseWriter, u *url.URL, total int64, page, itemsPerPage int) {
if itemsPerPage <= 0 {
itemsPerPage = 1
}

itemsPerPage64 := int64(itemsPerPage)
offset := int64(page) * itemsPerPage64

// lastOffset will either equal the offset required to contain the remainder,
// or the limit.
var lastOffset int64
if total%itemsPerPage64 == 0 {
lastOffset = total - itemsPerPage64
} else {
lastOffset = (total / itemsPerPage64) * itemsPerPage64
}

// Check for last page
if offset >= lastOffset {
if total == 0 {
w.Header().Set("Link", strings.Join([]string{
header(u, "first", itemsPerPage64, 0),
header(u, "next", itemsPerPage64, ((offset/itemsPerPage64)+1)*itemsPerPage64),
header(u, "prev", itemsPerPage64, ((offset/itemsPerPage64)-1)*itemsPerPage64),
}, ","))
return
}

if total < itemsPerPage64 {
w.Header().Set("link", header(u, "first", total, 0))
return
}

w.Header().Set("Link", strings.Join([]string{
header(u, "first", itemsPerPage64, 0),
header(u, "prev", itemsPerPage64, lastOffset-itemsPerPage64),
}, ","))
return
}

if offset < itemsPerPage64 {
w.Header().Set("Link", strings.Join([]string{
header(u, "next", itemsPerPage64, itemsPerPage64),
header(u, "last", itemsPerPage64, lastOffset),
}, ","))
return
}

w.Header().Set("Link", strings.Join([]string{
header(u, "first", itemsPerPage64, 0),
header(u, "next", itemsPerPage64, ((offset/itemsPerPage64)+1)*itemsPerPage64),
header(u, "prev", itemsPerPage64, ((offset/itemsPerPage64)-1)*itemsPerPage64),
header(u, "last", itemsPerPage64, lastOffset),
}, ","))
pagepagination.PaginationHeader(w, u, total, page, itemsPerPage)
}
133 changes: 0 additions & 133 deletions x/pagination_test.go

This file was deleted.

0 comments on commit b633ec3

Please sign in to comment.