From 3871a1861a652fd60435c8869302c3feef7e4e89 Mon Sep 17 00:00:00 2001 From: Dalton Hubble Date: Wed, 27 Oct 2021 11:19:14 -0700 Subject: [PATCH 1/2] Parse Before/After Links into Response * Some Github APIs use `before`/`after` for pagination, rather than `page` or `cursor` pagination. Parse these response values * For example, the Organizations GetAuditLog (Enterprise Cloud) https://docs.github.com/en/rest/reference/orgs#get-the-audit-log-for-an-organization With this change, pagination can be performed ```go for pageCount < PageMax { entries, resp, err := client.Organizations.GetAuditLog(ctx, "org", auditParams) if err != nil { return err } pageCount++ if resp.After == "" { break } auditParams.After = resp.After } ``` --- github/github.go | 10 +++++++++- github/github_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/github/github.go b/github/github.go index d4d7a54a7f1..28b5a51f976 100644 --- a/github/github.go +++ b/github/github.go @@ -462,6 +462,10 @@ type Response struct { // Set ListCursorOptions.Cursor to this value when calling the endpoint again. Cursor string + // For APIs that support before/after pagniation, such as OrganizationsService.AuditLog. + Before string + After string + // Explicitly specify the Rate type so Rate's String() receiver doesn't // propagate to Response. Rate Rate @@ -517,7 +521,9 @@ func (r *Response) populatePageValues() { } page := q.Get("page") - if page == "" { + before := q.Get("before") + after := q.Get("after") + if page == "" && before == "" && after == "" { continue } @@ -527,8 +533,10 @@ func (r *Response) populatePageValues() { if r.NextPage, err = strconv.Atoi(page); err != nil { r.NextPageToken = page } + r.After = after case `rel="prev"`: r.PrevPage, _ = strconv.Atoi(page) + r.Before = before case `rel="first"`: r.FirstPage, _ = strconv.Atoi(page) case `rel="last"`: diff --git a/github/github_test.go b/github/github_test.go index 08d2c8ad990..dfa0d3389ae 100644 --- a/github/github_test.go +++ b/github/github_test.go @@ -688,6 +688,40 @@ func TestResponse_cursorPagination(t *testing.T) { } } +func TestResponse_beforeAfterPagination(t *testing.T) { + r := http.Response{ + Header: http.Header{ + "Link": {`; rel="next",` + + ` ; rel="first",` + + ` ; rel="prev",`, + }, + }, + } + + response := newResponse(&r) + if got, want := response.Before, "d4e5f6"; got != want { + t.Errorf("response.Before: %v, want %v", got, want) + } + if got, want := response.After, "a1b2c3"; got != want { + t.Errorf("response.After: %v, want %v", got, want) + } + if got, want := response.FirstPage, 0; got != want { + t.Errorf("response.FirstPage: %v, want %v", got, want) + } + if got, want := response.PrevPage, 0; want != got { + t.Errorf("response.PrevPage: %v, want %v", got, want) + } + if got, want := response.NextPage, 0; want != got { + t.Errorf("response.NextPage: %v, want %v", got, want) + } + if got, want := response.LastPage, 0; want != got { + t.Errorf("response.LastPage: %v, want %v", got, want) + } + if got, want := response.NextPageToken, ""; want != got { + t.Errorf("response.NextPageToken: %v, want %v", got, want) + } +} + func TestResponse_populatePageValues_invalid(t *testing.T) { r := http.Response{ Header: http.Header{ From cc18ba544603fedd1343197b5150eb945dead8fd Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Mon, 15 Nov 2021 11:51:01 -0500 Subject: [PATCH 2/2] Update github/github.go Co-authored-by: Parker77 <20973702+Parker77@users.noreply.github.com> --- github/github.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/github.go b/github/github.go index 28b5a51f976..5f26aca93d7 100644 --- a/github/github.go +++ b/github/github.go @@ -462,7 +462,7 @@ type Response struct { // Set ListCursorOptions.Cursor to this value when calling the endpoint again. Cursor string - // For APIs that support before/after pagniation, such as OrganizationsService.AuditLog. + // For APIs that support before/after pagination, such as OrganizationsService.AuditLog. Before string After string