mirror of https://github.com/ory/kratos
66 lines
2.2 KiB
Go
66 lines
2.2 KiB
Go
// Copyright © 2023 Ory Corp
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package x
|
|
|
|
import (
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"github.com/ory/herodot"
|
|
"github.com/ory/x/pagination/keysetpagination"
|
|
"github.com/ory/x/pagination/migrationpagination"
|
|
"github.com/ory/x/pagination/pagepagination"
|
|
)
|
|
|
|
// The format we need to use in the Page tokens, as it's the only format that is understood by all DBs
|
|
const MapPaginationDateFormat = "2006-01-02 15:04:05.99999"
|
|
|
|
// ParsePagination parses limit and page from *http.Request with given limits and defaults.
|
|
func ParsePagination(r *http.Request) (page, itemsPerPage int) {
|
|
return migrationpagination.NewDefaultPaginator().ParsePagination(r)
|
|
}
|
|
|
|
func PaginationHeader(w http.ResponseWriter, u url.URL, total int64, page, itemsPerPage int) {
|
|
migrationpagination.PaginationHeader(w, &u, total, page, itemsPerPage)
|
|
}
|
|
|
|
type Page struct {
|
|
Page, ItemsPerPage int
|
|
}
|
|
|
|
var PagePaginationLimit = 1000
|
|
|
|
func ParseKeysetOrPagePagination(r *http.Request) ([]keysetpagination.Option, *Page, error) {
|
|
q := r.URL.Query()
|
|
// If we have any new-style pagination parameters, use those and ignore the rest.
|
|
if q.Has("page_token") || q.Has("page_size") {
|
|
keyset, err := keysetpagination.Parse(q, keysetpagination.NewStringPageToken)
|
|
if err != nil {
|
|
return nil, nil, herodot.ErrBadRequest.WithReason(err.Error())
|
|
}
|
|
return keyset, nil, nil
|
|
}
|
|
// allow fallback page pagination with upper limit
|
|
if q.Has("page") {
|
|
paginator := pagepagination.PagePaginator{MaxItems: 500, DefaultItems: 250}
|
|
page, perPage := paginator.ParsePagination(r)
|
|
if page*perPage > PagePaginationLimit {
|
|
return nil, nil, herodot.ErrBadRequest.WithReasonf("Legacy pagination is not supported for enumerating over %d items. Please switch to using page_token and page_size.", PagePaginationLimit)
|
|
}
|
|
return nil, &Page{page, perPage}, nil
|
|
}
|
|
// Allow passing per_page instead of page_size if only the former is set...
|
|
if q.Has("per_page") && !q.Has("page_size") {
|
|
q.Set("page_size", q.Get("per_page"))
|
|
q.Del("per_page")
|
|
r.URL.RawQuery = q.Encode()
|
|
}
|
|
// ... and defaul to keyset pagination
|
|
keyset, err := keysetpagination.Parse(q, keysetpagination.NewStringPageToken)
|
|
if err != nil {
|
|
return nil, nil, herodot.ErrBadRequest.WithReason(err.Error())
|
|
}
|
|
return keyset, nil, nil
|
|
}
|