Skip to content

Commit 84368c4

Browse files
bill-richBill Rich
andauthored
Loop over paginated responses (#183)
Co-authored-by: Bill Rich <[email protected]>
1 parent ff2633c commit 84368c4

File tree

1 file changed

+42
-40
lines changed

1 file changed

+42
-40
lines changed

client.go

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"fmt"
77
"io"
8+
"io/ioutil"
89
"log"
910
"mime/multipart"
1011
"net/http"
@@ -53,6 +54,15 @@ type auth struct {
5354
bearerToken string
5455
}
5556

57+
type Response struct {
58+
Size int `json:"size"`
59+
Page int `json:"page"`
60+
Pagelen int `json:"pagelen"`
61+
Next string `json:"next"`
62+
Previous string `json:"previous"`
63+
Values []interface{} `json:"values"`
64+
}
65+
5666
// Uses the Client Credentials Grant oauth2 flow to authenticate to Bitbucket
5767
func NewOAuthClientCredentials(i, s string) *Client {
5868
a := &auth{appID: i, secret: s}
@@ -229,44 +239,6 @@ func (c *Client) execute(method string, urlStr string, text string) (interface{}
229239
return nil, err
230240
}
231241

232-
//autopaginate.
233-
resultMap, isMap := result.(map[string]interface{})
234-
if isMap {
235-
nextIn := resultMap["next"]
236-
valuesIn := resultMap["values"]
237-
if nextIn != nil && valuesIn != nil {
238-
nextUrl := nextIn.(string)
239-
if nextUrl != "" {
240-
valuesSlice := valuesIn.([]interface{})
241-
if valuesSlice != nil {
242-
nextResult, err := c.execute(method, nextUrl, text)
243-
if err != nil {
244-
return nil, err
245-
}
246-
nextResultMap, isNextMap := nextResult.(map[string]interface{})
247-
if !isNextMap {
248-
return nil, fmt.Errorf("next page result is not map, it's %T", nextResult)
249-
}
250-
nextValuesIn := nextResultMap["values"]
251-
if nextValuesIn == nil {
252-
return nil, fmt.Errorf("next page result has no values")
253-
}
254-
nextValuesSlice, isSlice := nextValuesIn.([]interface{})
255-
if !isSlice {
256-
return nil, fmt.Errorf("next page result 'values' is not slice")
257-
}
258-
valuesSlice = append(valuesSlice, nextValuesSlice...)
259-
resultMap["values"] = valuesSlice
260-
delete(resultMap, "page")
261-
delete(resultMap, "pagelen")
262-
delete(resultMap, "max_depth")
263-
delete(resultMap, "size")
264-
result = resultMap
265-
}
266-
}
267-
}
268-
}
269-
270242
return result, nil
271243
}
272244

@@ -338,12 +310,42 @@ func (c *Client) doRequest(req *http.Request, emptyResponse bool) (interface{},
338310

339311
defer resBody.Close()
340312

313+
responseBytes, err := ioutil.ReadAll(resBody)
314+
if err != nil {
315+
return resBody, err
316+
}
317+
318+
responsePaginated := &Response{}
319+
err = json.Unmarshal(responseBytes, responsePaginated)
320+
if err == nil && len(responsePaginated.Values) > 0 {
321+
var values []interface{}
322+
for {
323+
values = append(values, responsePaginated.Values...)
324+
if len(responsePaginated.Next) == 0 {
325+
break
326+
}
327+
newReq, err := http.NewRequest(req.Method, responsePaginated.Next, nil)
328+
if err != nil {
329+
return resBody, err
330+
}
331+
resp, err := c.doRawRequest(newReq, false)
332+
if err != nil {
333+
return resBody, err
334+
}
335+
json.NewDecoder(resp).Decode(responsePaginated)
336+
}
337+
responsePaginated.Values = values
338+
responseBytes, err = json.Marshal(responsePaginated)
339+
if err != nil {
340+
return resBody, err
341+
}
342+
}
343+
341344
var result interface{}
342-
if err := json.NewDecoder(resBody).Decode(&result); err != nil {
345+
if err := json.Unmarshal(responseBytes, &result); err != nil {
343346
log.Println("Could not unmarshal JSON payload, returning raw response")
344347
return resBody, err
345348
}
346-
347349
return result, nil
348350
}
349351

0 commit comments

Comments
 (0)