diff --git a/api/handler/object_list_test.go b/api/handler/object_list_test.go index 0dbb5b8c..15f7c752 100644 --- a/api/handler/object_list_test.go +++ b/api/handler/object_list_test.go @@ -938,6 +938,29 @@ func TestPeriodicWriter(t *testing.T) { }) } +func TestListObjectsNotDuplicateContinuationToken(t *testing.T) { + tc := prepareHandlerContext(t) + + bktName := "bucket-for-listing" + bktInfo := createTestBucket(tc, bktName) + + for _, name := range []string{"bar /baz", "bar baz/foo", "bar/baz"} { + createTestObject(tc, bktInfo, name, encryption.Params{}) + } + + t.Run("list v2", func(t *testing.T) { + res1 := listObjectsV2(tc, bktName, "", "", "", "", 1) + res2 := listObjectsV2(tc, bktName, "", "", "", res1.NextContinuationToken, 1) + require.NotEqual(t, res1.NextContinuationToken, res2.NextContinuationToken) + }) + + t.Run("list versions", func(t *testing.T) { + res1 := listObjectsVersions(tc, bktName, "", "", "", "", 1) + res2 := listObjectsVersions(tc, bktName, "", "", res1.NextKeyMarker, res1.NextVersionIDMarker, 1) + require.NotEqual(t, res1.NextVersionIDMarker, res2.NextVersionIDMarker) + }) +} + func checkVersionsNames(t *testing.T, versions *ListObjectsVersionsResponse, names []string) { for i, v := range versions.Version { require.Equal(t, names[i], v.Key) diff --git a/api/layer/listing.go b/api/layer/listing.go index 50088ff5..21a1d778 100644 --- a/api/layer/listing.go +++ b/api/layer/listing.go @@ -161,7 +161,7 @@ func (n *Layer) ListObjectsV2(ctx context.Context, p *ListObjectsParamsV2) (*Lis if next != nil { result.IsTruncated = true - result.NextContinuationToken = next.NodeVersion.OID.EncodeToString() + result.NextContinuationToken = objects[len(objects)-1].NodeVersion.OID.EncodeToString() } result.Prefixes, result.Objects = triageExtendedObjects(objects) @@ -380,7 +380,7 @@ func (n *Layer) putListLatestVersionsSession(ctx context.Context, p commonLatest case ListObjectsV1Type: cacheKey = cache.CreateListSessionCacheKey(p.BktInfo.CID, p.Prefix, allObjects[p.MaxKeys-1].Name()) case ListObjectsV2Type: - cacheKey = cache.CreateListSessionCacheKey(p.BktInfo.CID, p.Prefix, allObjects[p.MaxKeys].NodeVersion.OID.EncodeToString()) + cacheKey = cache.CreateListSessionCacheKey(p.BktInfo.CID, p.Prefix, allObjects[p.MaxKeys-1].NodeVersion.OID.EncodeToString()) default: // should never happen panic("invalid list type")