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
20
21
22
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
35
36 var lastOffset int
37 if total%limit == 0 {
38 lastOffset = total - limit
39 } else {
40 lastOffset = (total / limit) * limit
41 }
42
43
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