Escapse the repository name in the link header returned in response (#11037)

Escapse the repository name in the link header returned in response

Signed-off-by: Wenkai Yin <yinw@vmware.com>
This commit is contained in:
Wenkai Yin(尹文开) 2020-03-18 14:29:15 +08:00 committed by GitHub
parent 7d20154db5
commit 798dda8604
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 25 deletions

View File

@ -17,7 +17,6 @@ package q
import (
"fmt"
ierror "github.com/goharbor/harbor/src/internal/error"
"net/url"
"strconv"
"strings"
"time"
@ -39,15 +38,6 @@ func Build(q string, pageNumber, pageSize int64) (*Query, error) {
if len(q) == 0 {
return query, nil
}
// unescape the query string
// when the query string is returned in the link header, they are all escaped
qs, err := url.QueryUnescape(q)
if err != nil {
return nil, ierror.New(err).
WithCode(ierror.BadRequestCode).
WithMessage("invalid query string: %s", q)
}
q = qs
params := strings.Split(q, ",")
for _, param := range params {
strs := strings.SplitN(param, "=", 2)

View File

@ -262,12 +262,4 @@ func TestBuild(t *testing.T) {
assert.Equal(t, int64(1), query.PageNumber)
assert.Equal(t, int64(10), query.PageSize)
assert.Equal(t, "v", query.Keywords["k"].(string))
// contains escaped characters
q = `k%3Dv`
query, err = Build(q, 1, 10)
require.Nil(t, err)
assert.Equal(t, int64(1), query.PageNumber)
assert.Equal(t, int64(10), query.PageSize)
assert.Equal(t, "v", query.Keywords["k"].(string))
}

View File

@ -121,26 +121,44 @@ func (b *BaseAPI) BuildQuery(ctx context.Context, query *string, pageNumber, pag
// Links return Links based on the provided pagination information
func (b *BaseAPI) Links(ctx context.Context, u *url.URL, total, pageNumber, pageSize int64) internal.Links {
url := *u
ul := *u
// try to unescape the repository name which contains escaped slashes
if escapedPath, err := url.PathUnescape(ul.Path); err == nil {
ul.Path = escapedPath
} else {
log.Errorf("failed to unescape the path %s: %v", ul.Path, err)
}
var links internal.Links
// prev
if pageNumber > 1 && (pageNumber-1)*pageSize < total {
q := url.Query()
q := ul.Query()
q.Set("page", strconv.FormatInt(pageNumber-1, 10))
url.RawQuery = q.Encode()
ul.RawQuery = q.Encode()
// try to unescape the query
if escapedQuery, err := url.QueryUnescape(ul.RawQuery); err == nil {
ul.RawQuery = escapedQuery
} else {
log.Errorf("failed to unescape the query %s: %v", ul.RawQuery, err)
}
link := &internal.Link{
URL: url.String(),
URL: ul.String(),
Rel: "prev",
}
links = append(links, link)
}
// next
if pageSize*pageNumber < total {
q := url.Query()
q := ul.Query()
q.Set("page", strconv.FormatInt(pageNumber+1, 10))
url.RawQuery = q.Encode()
ul.RawQuery = q.Encode()
// try to unescape the query
if escapedQuery, err := url.QueryUnescape(ul.RawQuery); err == nil {
ul.RawQuery = escapedQuery
} else {
log.Errorf("failed to unescape the query %s: %v", ul.RawQuery, err)
}
link := &internal.Link{
URL: url.String(),
URL: ul.String(),
Rel: "next",
}
links = append(links, link)

View File

@ -81,6 +81,16 @@ func (b *baseHandlerTestSuite) TestLinks() {
b.Equal("http://localhost/api/artifacts?page=1&page_size=1", links[0].URL)
b.Equal("next", links[1].Rel)
b.Equal("http://localhost/api/artifacts?page=3&page_size=1", links[1].URL)
// path and query contain escaped characters
url, err = url.Parse("http://localhost/api/library%252Fhello-world/artifacts?page=2&page_size=1&q=a%3D~b")
b.Require().Nil(err)
links = b.base.Links(nil, url, 3, 2, 1)
b.Require().Len(links, 2)
b.Equal("prev", links[0].Rel)
b.Equal("http://localhost/api/library/hello-world/artifacts?page=1&page_size=1&q=a=~b", links[0].URL)
b.Equal("next", links[1].Rel)
b.Equal("http://localhost/api/library/hello-world/artifacts?page=3&page_size=1&q=a=~b", links[1].URL)
}
func TestBaseHandler(t *testing.T) {