summaryrefslogtreecommitdiffstats
path: root/modules/context
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2019-06-26 16:51:32 +0800
committerGitHub <noreply@github.com>2019-06-26 16:51:32 +0800
commit42729b7562cfcdd7fe554a381c48360ca63c6932 (patch)
tree1cbf54dbbde11bfd7447d30e489360246de65afd /modules/context
parent5908bb103003912bd0ba3cefa66f2ff815ee8d8e (diff)
downloadgitea-42729b7562cfcdd7fe554a381c48360ca63c6932.tar.gz
gitea-42729b7562cfcdd7fe554a381c48360ca63c6932.zip
fix API link header (#7298)
Diffstat (limited to 'modules/context')
-rw-r--r--modules/context/api.go41
-rw-r--r--modules/context/api_test.go51
2 files changed, 85 insertions, 7 deletions
diff --git a/modules/context/api.go b/modules/context/api.go
index 9be3fb512c..0b2f81fd64 100644
--- a/modules/context/api.go
+++ b/modules/context/api.go
@@ -7,6 +7,7 @@ package context
import (
"fmt"
+ "net/url"
"strings"
"github.com/go-macaron/csrf"
@@ -77,23 +78,49 @@ func (ctx *APIContext) Error(status int, title string, obj interface{}) {
})
}
-// SetLinkHeader sets pagination link header by given total number and page size.
-func (ctx *APIContext) SetLinkHeader(total, pageSize int) {
- page := NewPagination(total, pageSize, ctx.QueryInt("page"), 0)
+func genAPILinks(curURL *url.URL, total, pageSize, curPage int) []string {
+ page := NewPagination(total, pageSize, curPage, 0)
paginater := page.Paginater
links := make([]string, 0, 4)
+
if paginater.HasNext() {
- links = append(links, fmt.Sprintf("<%s%s?page=%d>; rel=\"next\"", setting.AppURL, ctx.Req.URL.Path[1:], paginater.Next()))
+ u := *curURL
+ queries := u.Query()
+ queries.Set("page", fmt.Sprintf("%d", paginater.Next()))
+ u.RawQuery = queries.Encode()
+
+ links = append(links, fmt.Sprintf("<%s%s>; rel=\"next\"", setting.AppURL, u.RequestURI()[1:]))
}
if !paginater.IsLast() {
- links = append(links, fmt.Sprintf("<%s%s?page=%d>; rel=\"last\"", setting.AppURL, ctx.Req.URL.Path[1:], paginater.TotalPages()))
+ u := *curURL
+ queries := u.Query()
+ queries.Set("page", fmt.Sprintf("%d", paginater.TotalPages()))
+ u.RawQuery = queries.Encode()
+
+ links = append(links, fmt.Sprintf("<%s%s>; rel=\"last\"", setting.AppURL, u.RequestURI()[1:]))
}
if !paginater.IsFirst() {
- links = append(links, fmt.Sprintf("<%s%s?page=1>; rel=\"first\"", setting.AppURL, ctx.Req.URL.Path[1:]))
+ u := *curURL
+ queries := u.Query()
+ queries.Set("page", "1")
+ u.RawQuery = queries.Encode()
+
+ links = append(links, fmt.Sprintf("<%s%s>; rel=\"first\"", setting.AppURL, u.RequestURI()[1:]))
}
if paginater.HasPrevious() {
- links = append(links, fmt.Sprintf("<%s%s?page=%d>; rel=\"prev\"", setting.AppURL, ctx.Req.URL.Path[1:], paginater.Previous()))
+ u := *curURL
+ queries := u.Query()
+ queries.Set("page", fmt.Sprintf("%d", paginater.Previous()))
+ u.RawQuery = queries.Encode()
+
+ links = append(links, fmt.Sprintf("<%s%s>; rel=\"prev\"", setting.AppURL, u.RequestURI()[1:]))
}
+ return links
+}
+
+// SetLinkHeader sets pagination link header by given total number and page size.
+func (ctx *APIContext) SetLinkHeader(total, pageSize int) {
+ links := genAPILinks(ctx.Req.URL, total, pageSize, ctx.QueryInt("page"))
if len(links) > 0 {
ctx.Header().Set("Link", strings.Join(links, ","))
diff --git a/modules/context/api_test.go b/modules/context/api_test.go
new file mode 100644
index 0000000000..e7e3e230af
--- /dev/null
+++ b/modules/context/api_test.go
@@ -0,0 +1,51 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package context
+
+import (
+ "net/url"
+ "strconv"
+ "testing"
+
+ "code.gitea.io/gitea/modules/setting"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGenAPILinks(t *testing.T) {
+ setting.AppURL = "http://localhost:3000/"
+ var kases = map[string][]string{
+ "api/v1/repos/jerrykan/example-repo/issues?state=all": {
+ `<http://localhost:3000/api/v1/repos/jerrykan/example-repo/issues?page=2&state=all>; rel="next"`,
+ `<http://localhost:3000/api/v1/repos/jerrykan/example-repo/issues?page=5&state=all>; rel="last"`,
+ },
+ "api/v1/repos/jerrykan/example-repo/issues?state=all&page=1": {
+ `<http://localhost:3000/api/v1/repos/jerrykan/example-repo/issues?page=2&state=all>; rel="next"`,
+ `<http://localhost:3000/api/v1/repos/jerrykan/example-repo/issues?page=5&state=all>; rel="last"`,
+ },
+ "api/v1/repos/jerrykan/example-repo/issues?state=all&page=2": {
+ `<http://localhost:3000/api/v1/repos/jerrykan/example-repo/issues?page=3&state=all>; rel="next"`,
+ `<http://localhost:3000/api/v1/repos/jerrykan/example-repo/issues?page=5&state=all>; rel="last"`,
+ `<http://localhost:3000/api/v1/repos/jerrykan/example-repo/issues?page=1&state=all>; rel="first"`,
+ `<http://localhost:3000/api/v1/repos/jerrykan/example-repo/issues?page=1&state=all>; rel="prev"`,
+ },
+ "api/v1/repos/jerrykan/example-repo/issues?state=all&page=5": {
+ `<http://localhost:3000/api/v1/repos/jerrykan/example-repo/issues?page=1&state=all>; rel="first"`,
+ `<http://localhost:3000/api/v1/repos/jerrykan/example-repo/issues?page=4&state=all>; rel="prev"`,
+ },
+ }
+
+ for req, response := range kases {
+ u, err := url.Parse(setting.AppURL + req)
+ assert.NoError(t, err)
+
+ p := u.Query().Get("page")
+ curPage, _ := strconv.Atoi(p)
+
+ links := genAPILinks(u, 100, 20, curPage)
+
+ assert.EqualValues(t, links, response)
+ }
+}