Commit f8137824 authored by Maxime Roussin-Bélanger's avatar Maxime Roussin-Bélanger Committed by Sander van Harmelen

Add how many results and pages there are for a paginated api (#345)

parent d2dc01ef
...@@ -38,6 +38,13 @@ const ( ...@@ -38,6 +38,13 @@ const (
libraryVersion = "0.2.0" libraryVersion = "0.2.0"
defaultBaseURL = "https://gitlab.com/api/v4/" defaultBaseURL = "https://gitlab.com/api/v4/"
userAgent = "go-gitlab/" + libraryVersion userAgent = "go-gitlab/" + libraryVersion
headerNextPage = "X-Next-Page"
headerTotalPages = "X-Total-Pages"
headertotalResults = "X-Total"
headerCurrentPage = "X-Page"
headerPerPage = "X-Per-Page"
headerPrevPage = "X-Prev-Page"
) )
// tokenType represents a token type within GitLab. // tokenType represents a token type within GitLab.
...@@ -492,10 +499,12 @@ type Response struct { ...@@ -492,10 +499,12 @@ type Response struct {
// responses that are not part of a paginated set, or for which there // responses that are not part of a paginated set, or for which there
// are no additional pages. // are no additional pages.
NextPage int NextPage int
PrevPage int PrevPage int
FirstPage int CurrentPage int
LastPage int PerPage int
TotalPages int
TotalResults int
} }
// newResponse creates a new Response for the provided http.Response. // newResponse creates a new Response for the provided http.Response.
...@@ -508,44 +517,28 @@ func newResponse(r *http.Response) *Response { ...@@ -508,44 +517,28 @@ func newResponse(r *http.Response) *Response {
// populatePageValues parses the HTTP Link response headers and populates the // populatePageValues parses the HTTP Link response headers and populates the
// various pagination link values in the Response. // various pagination link values in the Response.
func (r *Response) populatePageValues() { func (r *Response) populatePageValues() {
if links, ok := r.Response.Header["Link"]; ok && len(links) > 0 { if totalPages := r.Response.Header.Get(headerTotalPages); totalPages != "" {
for _, link := range strings.Split(links[0], ",") { r.TotalPages, _ = strconv.Atoi(totalPages)
segments := strings.Split(strings.TrimSpace(link), ";") }
// link must at least have href and rel if totalResults := r.Response.Header.Get(headertotalResults); totalResults != "" {
if len(segments) < 2 { r.TotalResults, _ = strconv.Atoi(totalResults)
continue }
}
if nextPage := r.Response.Header.Get(headerNextPage); nextPage != "" {
// ensure href is properly formatted r.NextPage, _ = strconv.Atoi(nextPage)
if !strings.HasPrefix(segments[0], "<") || !strings.HasSuffix(segments[0], ">") { }
continue
} if currentPage := r.Response.Header.Get(headerCurrentPage); currentPage != "" {
r.CurrentPage, _ = strconv.Atoi(currentPage)
// try to pull out page parameter }
url, err := url.Parse(segments[0][1 : len(segments[0])-1])
if err != nil { if perPage := r.Response.Header.Get(headerPerPage); perPage != "" {
continue r.PerPage, _ = strconv.Atoi(perPage)
} }
page := url.Query().Get("page")
if page == "" { if prevPage := r.Response.Header.Get(headerPrevPage); prevPage != "" {
continue r.PrevPage, _ = strconv.Atoi(prevPage)
}
for _, segment := range segments[1:] {
switch strings.TrimSpace(segment) {
case `rel="next"`:
r.NextPage, _ = strconv.Atoi(page)
case `rel="prev"`:
r.PrevPage, _ = strconv.Atoi(page)
case `rel="first"`:
r.FirstPage, _ = strconv.Atoi(page)
case `rel="last"`:
r.LastPage, _ = strconv.Atoi(page)
}
}
}
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment