mirror of https://github.com/harness/drone.git
104 lines
3.0 KiB
Go
104 lines
3.0 KiB
Go
// Copyright 2023 Harness, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package render
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
)
|
|
|
|
// format string for the link header value.
|
|
var linkf = `<%s>; rel="%s"`
|
|
|
|
// Pagination writes the pagination and link headers to the http.Response.
|
|
func Pagination(r *http.Request, w http.ResponseWriter, page, size, total int) {
|
|
var (
|
|
last = pagelen(size, total)
|
|
)
|
|
|
|
// Add information that doesn't require total
|
|
PaginationNoTotal(r, w, page, size, page >= last)
|
|
|
|
// add information that requires total
|
|
uri := getPaginationBaseURL(r, page, size)
|
|
params := uri.Query()
|
|
|
|
// update the page query parameter and re-encode
|
|
params.Set("page", strconv.Itoa(last))
|
|
uri.RawQuery = params.Encode()
|
|
|
|
// write the page total to the header.
|
|
w.Header().Set("x-total", strconv.Itoa(total))
|
|
w.Header().Set("x-total-pages", strconv.Itoa(last))
|
|
w.Header().Add("Link", fmt.Sprintf(linkf, uri.String(), "last"))
|
|
}
|
|
|
|
// PaginationNoTotal writes the pagination and link headers to the http.Response when total is unknown.
|
|
func PaginationNoTotal(r *http.Request, w http.ResponseWriter, page int, size int, isLastPage bool) {
|
|
var (
|
|
next = page + 1
|
|
prev = max(page-1, 1)
|
|
)
|
|
|
|
// write basic headers
|
|
w.Header().Set("x-page", strconv.Itoa(page))
|
|
w.Header().Set("x-per-page", strconv.Itoa(size))
|
|
|
|
// write headers based on relative location of current page
|
|
uri := getPaginationBaseURL(r, page, size)
|
|
params := uri.Query()
|
|
|
|
if !isLastPage {
|
|
// update the page query parameter and re-encode
|
|
params.Set("page", strconv.Itoa(next))
|
|
uri.RawQuery = params.Encode()
|
|
|
|
// write the next page to the header.
|
|
w.Header().Set("x-next-page", strconv.Itoa(next))
|
|
w.Header().Add("Link", fmt.Sprintf(linkf, uri.String(), "next"))
|
|
}
|
|
|
|
if page > 1 {
|
|
// update the page query parameter and re-encode.
|
|
params.Set("page", strconv.Itoa(prev))
|
|
uri.RawQuery = params.Encode()
|
|
|
|
// write the previous page to the header.
|
|
w.Header().Set("x-prev-page", strconv.Itoa(prev))
|
|
w.Header().Add("Link", fmt.Sprintf(linkf, uri.String(), "prev"))
|
|
}
|
|
}
|
|
|
|
// PaginationLimit writes the x-total header.
|
|
func PaginationLimit(_ *http.Request, w http.ResponseWriter, total int) {
|
|
w.Header().Set("x-total", strconv.Itoa(total))
|
|
}
|
|
|
|
func getPaginationBaseURL(r *http.Request, page int, size int) url.URL {
|
|
uri := *r.URL
|
|
|
|
// parse the existing query parameters and
|
|
// sanize parameter list.
|
|
params := uri.Query()
|
|
params.Del("access_token")
|
|
params.Del("token")
|
|
params.Set("page", strconv.Itoa(page))
|
|
params.Set("limit", strconv.Itoa(size))
|
|
|
|
return uri
|
|
}
|