Resolve logic assumes lookup paths are sorted
for _, lookup := range response.Domain.LookupPaths {
isSubPath := strings.HasPrefix(urlPath, lookup.Prefix)
isRootPath := urlPath == path.Clean(lookup.Prefix)
if isSubPath || isRootPath {
subPath := ""
if isSubPath {
subPath = strings.TrimPrefix(urlPath, lookup.Prefix)
}
srv, err := g.fabricateServing(lookup)
if err != nil {
return nil, err
}
return &serving.Request{
Serving: srv,
LookupPath: fabricateLookupPath(size, lookup),
SubPath: subPath}, nil
}
}
When LookupPaths contains more element and the first one has a prefix of "/", then the statement strings.HasPrefix(urlPath, lookup.Prefix)
is true, so the serving request returned is the one for the root project rather than the actual project we want. For example, if the JSON response is:
{
"certificate": "some--cert",
"key": "some--key",
"lookup_paths": [
{
"access_control": false,
"https_only": true,
"prefix": "/",
"project_id": 125,
"source": {
"path": "some/path/to/group-project/",
"type": "file"
}
},
{
"access_control": false,
"https_only": true,
"prefix": "/my/second-project/",
"project_id": 124,
"source": {
"path": "some/path/to/project-2/",
"type": "file"
}
},
]
}
And Go unmarshals the response in the same order, then the statement above is true.
The following test asserts the failure
func TestResolveGroupFirst(t *testing.T) {
client := client.StubClient{File: "client/testdata/group-first.gitlab.io.json"}
source := Gitlab{client: client, enableDisk: true}
t.Run("when requesting the group root project with root path", func(t *testing.T) {
target := "https://group-first.gitlab.io:443/"
request := httptest.NewRequest("GET", target, nil)
response, err := source.Resolve(request)
require.NoError(t, err)
require.Equal(t, "/", response.LookupPath.Prefix)
require.Equal(t, "some/path/group/", response.LookupPath.Path)
require.Equal(t, "", response.SubPath)
require.True(t, response.LookupPath.IsNamespaceProject)
})
t.Run("when requesting another project with path", func(t *testing.T) {
target := "https://group-first.gitlab.io:443/my/second-project/index.html"
request := httptest.NewRequest("GET", target, nil)
response, err := source.Resolve(request)
require.NoError(t, err)
require.Equal(t, "/my/second-project/", response.LookupPath.Prefix)
require.Equal(t, "some/path/to/project-2/", response.LookupPath.Path)
require.Equal(t, "", response.SubPath)
require.False(t, response.LookupPath.IsNamespaceProject)
})
}
go test ./internal/source/gitlab -run TestResolveGroupFirst/when_requesting_another_project_with_path
--- FAIL: TestResolveGroupFirst (0.00s)
--- FAIL: TestResolveGroupFirst/when_requesting_another_project_with_path (0.00s)
gitlab_test.go:136:
Error Trace: gitlab_test.go:136
Error: Not equal:
expected: "/my/second-project/"
actual : "/"
Diff:
--- Expected
+++ Actual
@@ -1 +1 @@
-/my/second-project/
+/
Test: TestResolveGroupFirst/when_requesting_another_project_with_path
FAIL
FAIL gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab 0.133s
FAIL
Edited by Jaime Martinez