forked from johannesboyne/gofakes3
-
Notifications
You must be signed in to change notification settings - Fork 6
/
s300004_list_versions_with_version_marker_but_no_key_marker.go
144 lines (129 loc) · 5.12 KB
/
s300004_list_versions_with_version_marker_but_no_key_marker.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package main
import (
"bytes"
"fmt"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/s3"
)
// This test proved that version-id-marker requires key-marker to be passed
// when paginating object versions. This is a huge relief as it would've been
// really painful to support arbitrary combinations.
//
// This test flushed out that we are handling version-id-marker slightly wrong.
// The following debug dump shows that if version-id-marker is present in the
// query but contains an empty string, S3 rejects the request with an invalid
// argument error:
//
// GET /<bucket>?key-marker=810dd187e5ad28a83e8b208558823cf45d8d6e46b1f0fa56f2712de97213c343bbec1b871a4bfa92859cd142f25b9eb135008e47ad65359c4229b7919384d51dfd8f5b15e88eaec302a38447f86ef5642e03b10eac8ba81db5ddc949d769edf49e123b809800fa28e3ddef44bf96fe65ab422065e3378c9ff0c4c37a68e05f19af9d4755fbbd846cacecdaca95eecf9b9802685e7853&max-keys=1&prefix=810dd187e5ad28a83e8b208558823cf45d8d6e46b1f0fa56f2712de97213c343bbec1b871a4bfa92859cd142f25b9eb13500&version-id-marker=&versions=
// <Error>
// <Code>InvalidArgument</Code>
// <Message>A version-id marker cannot be empty.</Message>
// <ArgumentName>version-id-marker</ArgumentName><ArgumentValue></ArgumentValue>
// <RequestId>AC8DD6B6E4826D5C</RequestId>
// <HostId>prA+xN7N52Ovkry/Q8jMhvbCm2MtWiraIk2SOJqleareEgUY41CmpxD1Uvcaq6YiShSGoUlDbvY=</HostId>
// </Error>
//
// It looks as if key-marker is not validated the same way - if it's not passed,
// it just starts from the start, and ignores version-id-marker if one is passed.
//
type S300004ListVersionsWithVersionMarkerButNoKeyMarker struct{}
func (s S300004ListVersionsWithVersionMarkerButNoKeyMarker) Run(ctx *Context) error {
client := ctx.S3Client()
config := ctx.Config()
bucket := aws.String(config.BucketStandard())
if err := ctx.EnsureVersioningEnabled(client, config.BucketStandard()); err != nil {
return err
}
prefix := ctx.RandString(50)
key1, key2 := prefix+ctx.RandString(100), prefix+ctx.RandString(100)
keys := []string{key1, key2}
versions := map[string][]string{}
for _, key := range keys {
for i := 0; i < 2; i++ {
body := ctx.RandBytes(32)
vrs, err := client.PutObject(&s3.PutObjectInput{
Key: aws.String(key),
Bucket: bucket,
Body: bytes.NewReader(body),
})
if err != nil {
return err
}
versions[key] = append(versions[key], aws.StringValue(vrs.VersionId))
}
}
{ // Sanity check version length
rs, err := client.ListObjectVersions(&s3.ListObjectVersionsInput{
Bucket: bucket,
Prefix: aws.String(prefix),
})
if err != nil {
return err
}
if len(rs.Versions) != 4 {
return fmt.Errorf("unexpected version length")
}
}
page1, err := client.ListObjectVersions(&s3.ListObjectVersionsInput{
Bucket: bucket,
Prefix: aws.String(prefix),
MaxKeys: aws.Int64(1),
})
if err != nil {
return err
}
// Passing no key marker, which should be an error:
if _, err := client.ListObjectVersions(&s3.ListObjectVersionsInput{
Bucket: bucket,
Prefix: aws.String(prefix),
MaxKeys: aws.Int64(1),
VersionIdMarker: page1.NextVersionIdMarker,
}); err == nil {
return fmt.Errorf("expected error")
} else if serr, ok := err.(awserr.RequestFailure); !ok {
return fmt.Errorf("unexpected error %v", serr)
} else if serr.Code() != "InvalidArgument" || !strings.Contains(serr.Message(), "version-id marker cannot be specified without a key marker") {
return fmt.Errorf("unexpected error %v", serr)
}
// Passing key marker but empty version, which should fail:
if _, err := client.ListObjectVersions(&s3.ListObjectVersionsInput{
Bucket: bucket,
Prefix: aws.String(prefix),
MaxKeys: aws.Int64(1),
KeyMarker: page1.NextKeyMarker,
VersionIdMarker: aws.String(""),
}); err == nil {
return fmt.Errorf("expected error")
} else if serr, ok := err.(awserr.RequestFailure); !ok {
return fmt.Errorf("unexpected error %v", serr)
} else if serr.Code() != "InvalidArgument" || !strings.Contains(serr.Message(), "version-id marker cannot be empty") {
return fmt.Errorf("unexpected error %v", serr)
}
// Passing version-id-marker but empty key-marker returns the first page for some reason:
resultPage, err := client.ListObjectVersions(&s3.ListObjectVersionsInput{
Bucket: bucket,
Prefix: aws.String(prefix),
MaxKeys: aws.Int64(1),
KeyMarker: aws.String(""),
VersionIdMarker: page1.NextVersionIdMarker,
})
if err != nil {
return fmt.Errorf("unexpected error %v", err)
}
if aws.StringValue(resultPage.Versions[0].VersionId) != aws.StringValue(page1.Versions[0].VersionId) {
return fmt.Errorf("unexpected version id %s, expected %s",
aws.StringValue(resultPage.Versions[0].VersionId), aws.StringValue(page1.Versions[0].VersionId))
}
// Passing key marker but no version, which should be fine:
if _, err := client.ListObjectVersions(&s3.ListObjectVersionsInput{
Bucket: bucket,
Prefix: aws.String(prefix),
MaxKeys: aws.Int64(1),
KeyMarker: page1.NextKeyMarker,
}); err != nil {
return fmt.Errorf("unexpected error")
}
return nil
}