Skip to content

Commit fbf9d35

Browse files
authored
feat: add token pagination link header parser (#722)
1 parent d1b24d4 commit fbf9d35

File tree

4 files changed

+96
-0
lines changed

4 files changed

+96
-0
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ require (
5858
github.com/ory/herodot v0.9.13
5959
github.com/ory/jsonschema/v3 v3.0.7
6060
github.com/pelletier/go-toml v1.9.5
61+
github.com/peterhellberg/link v1.2.0
6162
github.com/pkg/errors v0.9.1
6263
github.com/pkg/profile v1.7.0
6364
github.com/prometheus/client_golang v1.13.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,8 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v
752752
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
753753
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
754754
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
755+
github.com/peterhellberg/link v1.2.0 h1:UA5pg3Gp/E0F2WdX7GERiNrPQrM1K6CVJUUWfHa4t6c=
756+
github.com/peterhellberg/link v1.2.0/go.mod h1:gYfAh+oJgQu2SrZHg5hROVRQe1ICoK0/HHJTcE0edxc=
755757
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
756758
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
757759
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright © 2023 Ory Corp
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package keysetpagination
5+
6+
import (
7+
"net/http"
8+
"net/url"
9+
10+
"github.com/peterhellberg/link"
11+
)
12+
13+
// PaginationResult represents a parsed result of the link HTTP header.
14+
type PaginationResult struct {
15+
// NextToken is the next page token. If it's empty, there is no next page.
16+
NextToken string
17+
18+
// FirstToken is the first page token.
19+
FirstToken string
20+
}
21+
22+
// ParseHeader parses the response header's Link.
23+
func ParseHeader(r *http.Response) *PaginationResult {
24+
links := link.ParseResponse(r)
25+
return &PaginationResult{
26+
NextToken: findRel(links, "next"),
27+
FirstToken: findRel(links, "first"),
28+
}
29+
}
30+
31+
func findRel(links link.Group, rel string) string {
32+
for idx, l := range links {
33+
if idx == rel {
34+
parsed, err := url.Parse(l.URI)
35+
if err != nil {
36+
continue
37+
}
38+
39+
return parsed.Query().Get("page_token")
40+
}
41+
}
42+
43+
return ""
44+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright © 2023 Ory Corp
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package keysetpagination
5+
6+
import (
7+
"net/http"
8+
"net/http/httptest"
9+
"net/url"
10+
"testing"
11+
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
)
15+
16+
func TestParseHeader(t *testing.T) {
17+
u, err := url.Parse("https://www.ory.sh/")
18+
require.NoError(t, err)
19+
20+
t.Run("has next page", func(t *testing.T) {
21+
p := &Paginator{
22+
defaultToken: StringPageToken("default"),
23+
token: StringPageToken("next"),
24+
size: 2,
25+
}
26+
27+
r := httptest.NewRecorder()
28+
Header(r, u, p)
29+
30+
result := ParseHeader(&http.Response{Header: r.Header()})
31+
assert.Equal(t, "next", result.NextToken, r.Header())
32+
assert.Equal(t, "default", result.FirstToken, r.Header())
33+
})
34+
35+
t.Run("is last page", func(t *testing.T) {
36+
p := &Paginator{
37+
defaultToken: StringPageToken("default"),
38+
size: 1,
39+
isLast: true,
40+
}
41+
42+
r := httptest.NewRecorder()
43+
Header(r, u, p)
44+
45+
result := ParseHeader(&http.Response{Header: r.Header()})
46+
assert.Equal(t, "", result.NextToken, r.Header())
47+
assert.Equal(t, "default", result.FirstToken, r.Header())
48+
})
49+
}

0 commit comments

Comments
 (0)