m[2] is the third element of m, rather than the second, so we have to check instead that the len of m is at least 3. Because the regular expression has two capture groups, the length of m will always be 3, so currently the guard will always be true.
108 lines
1.9 KiB
Go
108 lines
1.9 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
var linkRE = regexp.MustCompile(`<([^>]+)>;\s*rel="([^"]+)"`)
|
|
|
|
func findNextPage(resp *http.Response) (string, bool) {
|
|
for _, m := range linkRE.FindAllStringSubmatch(resp.Header.Get("Link"), -1) {
|
|
if len(m) > 2 && m[2] == "next" {
|
|
return m[1], true
|
|
}
|
|
}
|
|
return "", false
|
|
}
|
|
|
|
func findEndCursor(r io.Reader) string {
|
|
dec := json.NewDecoder(r)
|
|
|
|
var idx int
|
|
var stack []json.Delim
|
|
var lastKey string
|
|
var contextKey string
|
|
|
|
var endCursor string
|
|
var hasNextPage bool
|
|
var foundEndCursor bool
|
|
var foundNextPage bool
|
|
|
|
loop:
|
|
for {
|
|
t, err := dec.Token()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
switch tt := t.(type) {
|
|
case json.Delim:
|
|
switch tt {
|
|
case '{', '[':
|
|
stack = append(stack, tt)
|
|
contextKey = lastKey
|
|
idx = 0
|
|
case '}', ']':
|
|
stack = stack[:len(stack)-1]
|
|
contextKey = ""
|
|
idx = 0
|
|
}
|
|
default:
|
|
isKey := len(stack) > 0 && stack[len(stack)-1] == '{' && idx%2 == 0
|
|
idx++
|
|
|
|
switch tt := t.(type) {
|
|
case string:
|
|
if isKey {
|
|
lastKey = tt
|
|
} else if contextKey == "pageInfo" && lastKey == "endCursor" {
|
|
endCursor = tt
|
|
foundEndCursor = true
|
|
if foundNextPage {
|
|
break loop
|
|
}
|
|
}
|
|
case bool:
|
|
if contextKey == "pageInfo" && lastKey == "hasNextPage" {
|
|
hasNextPage = tt
|
|
foundNextPage = true
|
|
if foundEndCursor {
|
|
break loop
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if hasNextPage {
|
|
return endCursor
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func addPerPage(p string, perPage int, params map[string]interface{}) string {
|
|
if _, hasPerPage := params["per_page"]; hasPerPage {
|
|
return p
|
|
}
|
|
|
|
idx := strings.IndexRune(p, '?')
|
|
sep := "?"
|
|
|
|
if idx >= 0 {
|
|
if qp, err := url.ParseQuery(p[idx+1:]); err == nil && qp.Get("per_page") != "" {
|
|
return p
|
|
}
|
|
sep = "&"
|
|
}
|
|
|
|
return fmt.Sprintf("%s%sper_page=%d", p, sep, perPage)
|
|
}
|