X Tutup
Skip to content

Commit c945fb4

Browse files
committed
Automatically add per_page=100 to paginated REST requests
Most endpoints respect this parameter by default. Those that don't will just ignore it. The `per_page=100` parameter is not added if there is already a `per_page` parameter specified in the request.
1 parent f4ecd36 commit c945fb4

File tree

4 files changed

+79
-2
lines changed

4 files changed

+79
-2
lines changed

pkg/cmd/api/api.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ func apiRun(opts *ApiOptions) error {
143143
return err
144144
}
145145

146+
isGraphQL := opts.RequestPath == "graphql"
146147
requestPath, err := fillPlaceholders(opts.RequestPath, opts)
147148
if err != nil {
148149
return fmt.Errorf("unable to expand placeholder in path: %w", err)
@@ -155,6 +156,10 @@ func apiRun(opts *ApiOptions) error {
155156
method = "POST"
156157
}
157158

159+
if opts.Paginate && !isGraphQL {
160+
requestPath = addPerPage(requestPath, 100, params)
161+
}
162+
158163
if opts.RequestInputFile != "" {
159164
file, size, err := openUserFile(opts.RequestInputFile, opts.IO.In)
160165
if err != nil {
@@ -189,7 +194,7 @@ func apiRun(opts *ApiOptions) error {
189194
break
190195
}
191196

192-
if opts.RequestPath == "graphql" {
197+
if isGraphQL {
193198
hasNextPage = endCursor != ""
194199
if hasNextPage {
195200
params["endCursor"] = endCursor

pkg/cmd/api/api_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ func Test_apiRun_paginationREST(t *testing.T) {
343343
assert.Equal(t, `{"page":1}{"page":2}{"page":3}`, stdout.String(), "stdout")
344344
assert.Equal(t, "", stderr.String(), "stderr")
345345

346-
assert.Equal(t, "https://api.github.com/issues", responses[0].Request.URL.String())
346+
assert.Equal(t, "https://api.github.com/issues?per_page=100", responses[0].Request.URL.String())
347347
assert.Equal(t, "https://api.github.com/repositories/1227/issues?page=2", responses[1].Request.URL.String())
348348
assert.Equal(t, "https://api.github.com/repositories/1227/issues?page=3", responses[2].Request.URL.String())
349349
}

pkg/cmd/api/pagination.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ package api
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"io"
67
"net/http"
8+
"net/url"
79
"regexp"
10+
"strings"
811
)
912

1013
var linkRE = regexp.MustCompile(`<([^>]+)>;\s*rel="([^"]+)"`)
@@ -85,3 +88,21 @@ loop:
8588
}
8689
return ""
8790
}
91+
92+
func addPerPage(p string, perPage int, params map[string]interface{}) string {
93+
if _, hasPerPage := params["per_page"]; hasPerPage {
94+
return p
95+
}
96+
97+
idx := strings.IndexRune(p, '?')
98+
sep := "?"
99+
100+
if idx >= 0 {
101+
if qp, err := url.ParseQuery(p[idx+1:]); err == nil && qp.Get("per_page") != "" {
102+
return p
103+
}
104+
sep = "&"
105+
}
106+
107+
return fmt.Sprintf("%s%sper_page=%d", p, sep, perPage)
108+
}

pkg/cmd/api/pagination_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,54 @@ func Test_findEndCursor(t *testing.T) {
116116
})
117117
}
118118
}
119+
120+
func Test_addPerPage(t *testing.T) {
121+
type args struct {
122+
p string
123+
perPage int
124+
params map[string]interface{}
125+
}
126+
tests := []struct {
127+
name string
128+
args args
129+
want string
130+
}{
131+
{
132+
name: "adds per_page",
133+
args: args{
134+
p: "items",
135+
perPage: 13,
136+
params: nil,
137+
},
138+
want: "items?per_page=13",
139+
},
140+
{
141+
name: "avoids adding per_page if already in params",
142+
args: args{
143+
p: "items",
144+
perPage: 13,
145+
params: map[string]interface{}{
146+
"state": "open",
147+
"per_page": 99,
148+
},
149+
},
150+
want: "items",
151+
},
152+
{
153+
name: "avoids adding per_page if already in query",
154+
args: args{
155+
p: "items?per_page=6&state=open",
156+
perPage: 13,
157+
params: nil,
158+
},
159+
want: "items?per_page=6&state=open",
160+
},
161+
}
162+
for _, tt := range tests {
163+
t.Run(tt.name, func(t *testing.T) {
164+
if got := addPerPage(tt.args.p, tt.args.perPage, tt.args.params); got != tt.want {
165+
t.Errorf("addPerPage() = %v, want %v", got, tt.want)
166+
}
167+
})
168+
}
169+
}

0 commit comments

Comments
 (0)
X Tutup