...

Source file src/github.com/ory/x/pagination/header.go

Documentation: github.com/ory/x/pagination

     1  package pagination
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"net/url"
     7  	"strconv"
     8  	"strings"
     9  )
    10  
    11  func header(u *url.URL, rel string, limit, offset int) string {
    12  	q := u.Query()
    13  	q.Set("limit", strconv.Itoa(limit))
    14  	q.Set("offset", strconv.Itoa(offset))
    15  	u.RawQuery = q.Encode()
    16  	return fmt.Sprintf("<%s>; rel=\"%s\"", u.String(), rel)
    17  }
    18  
    19  // Header adds an http header for pagination using a responsewriter where backwards compatibility is required.
    20  // The header will contain links any combination of the first, last, next, or previous (prev) pages in a paginated list (given a limit and an offset, and optionally a total).
    21  // If total is not set, then no "last" page will be calculated.
    22  // If no limit is provided, then it will default to 1.
    23  func Header(w http.ResponseWriter, u *url.URL, total int, limit, offset int) {
    24  	if offset < 0 {
    25  		offset = 0
    26  	}
    27  
    28  	if limit <= 0 {
    29  		limit = 1
    30  	}
    31  
    32  	w.Header().Set("X-Total-Count", strconv.Itoa(total))
    33  
    34  	// lastOffset will either equal the offset required to contain the remainder,
    35  	// or the limit.
    36  	var lastOffset int
    37  	if total%limit == 0 {
    38  		lastOffset = total - limit
    39  	} else {
    40  		lastOffset = (total / limit) * limit
    41  	}
    42  
    43  	// Check for last page
    44  	if offset >= lastOffset {
    45  		if total == 0 {
    46  			w.Header().Set("Link", strings.Join([]string{
    47  				header(u, "first", limit, 0),
    48  				header(u, "next", limit, ((offset/limit)+1)*limit),
    49  				header(u, "prev", limit, ((offset/limit)-1)*limit),
    50  			}, ","))
    51  			return
    52  		}
    53  
    54  		if total < limit {
    55  			w.Header().Set("link", header(u, "first", total, 0))
    56  			return
    57  		}
    58  
    59  		w.Header().Set("Link", strings.Join([]string{
    60  			header(u, "first", limit, 0),
    61  			header(u, "prev", limit, lastOffset-limit),
    62  		}, ","))
    63  		return
    64  	}
    65  
    66  	if offset < limit {
    67  		w.Header().Set("Link", strings.Join([]string{
    68  			header(u, "next", limit, limit),
    69  			header(u, "last", limit, lastOffset),
    70  		}, ","))
    71  		return
    72  	}
    73  
    74  	w.Header().Set("Link", strings.Join([]string{
    75  		header(u, "first", limit, 0),
    76  		header(u, "next", limit, ((offset/limit)+1)*limit),
    77  		header(u, "prev", limit, ((offset/limit)-1)*limit),
    78  		header(u, "last", limit, lastOffset),
    79  	}, ","))
    80  	return
    81  }
    82  

View as plain text