@@ -57,15 +57,39 @@ func WithMaxKeys(maxKeys int32) ClientOption {
5757 }
5858}
5959
60+ // WithDelimiter sets a delimiter for grouping keys in List calls.
61+ func WithDelimiter (delimiter string ) ClientOption {
62+ return func (co * ClientOptions ) {
63+ co .Delimiter = aws .String (delimiter )
64+ }
65+ }
66+
67+ // WithPrefix sets the prefix to filter keys in List calls.
68+ func WithPrefix (prefix string ) ClientOption {
69+ return func (co * ClientOptions ) {
70+ co .Prefix = aws .String (prefix )
71+ }
72+ }
73+
74+ // WithPaginationToken sets the pagination token to continue listing objects.
75+ func WithPaginationToken (token string ) ClientOption {
76+ return func (co * ClientOptions ) {
77+ co .PaginationToken = aws .String (token )
78+ }
79+ }
80+
6081// ClientOptions is the collection of options that are set for individual Tigris
6182// calls.
6283type ClientOptions struct {
6384 BucketName string
6485 S3Options []func (* s3.Options )
6586
6687 // List options
67- StartAfter * string
68- MaxKeys * int32
88+ StartAfter * string
89+ MaxKeys * int32
90+ Delimiter * string
91+ Prefix * string
92+ PaginationToken * string
6993}
7094
7195// defaults populates client options from the global Options.
@@ -130,14 +154,23 @@ func New(ctx context.Context, options ...Option) (*Client, error) {
130154// Some calls may not populate all fields. Ensure that the values are valid before
131155// consuming them.
132156type Object struct {
133- Bucket string // Bucket the object is in
134- Key string // Key for the object
135- ContentType string // MIME type for the object or application/octet-stream
136- Etag string // Entity tag for the object (usually a checksum)
137- Version string // Version tag for the object
138- Size int64 // Size of the object in bytes or 0 if unknown
139- LastModified time.Time // Creation date of the object
140- Body io.ReadCloser // Body of the object so it can be read, don't forget to close it.
157+ Bucket string // Bucket the object is in
158+ Key string // Key for the object
159+ ContentType string // MIME type for the object or application/octet-stream
160+ ContentDisposition string // Content disposition of the object (inline or attachment)
161+ Etag string // Entity tag for the object (usually a checksum)
162+ Version string // Version tag for the object
163+ Size int64 // Size of the object in bytes or 0 if unknown
164+ LastModified time.Time // Creation date of the object
165+ URL string // Public or presigned URL for the object
166+ Body io.ReadCloser // Body of the object so it can be read, don't forget to close it.
167+ }
168+
169+ // ListResult contains the result of a List operation, including pagination information.
170+ type ListResult struct {
171+ Items []Object // List of objects
172+ NextToken string // Pagination token for the next page
173+ HasMore bool // Whether there are more objects to list
141174}
142175
143176// Get fetches the contents of an object and its metadata from Tigris.
@@ -226,8 +259,12 @@ func (c *Client) Delete(ctx context.Context, key string, opts ...ClientOption) e
226259 return nil
227260}
228261
229- // List returns a list of objects matching a key prefix.
230- func (c * Client ) List (ctx context.Context , prefix string , opts ... ClientOption ) ([]Object , error ) {
262+ // List returns a list of objects matching the given criteria.
263+ //
264+ // The returned ListResult contains pagination information; use NextToken with
265+ // WithPaginationToken() to fetch the next page. HasMore indicates whether
266+ // additional objects are available.
267+ func (c * Client ) List (ctx context.Context , opts ... ClientOption ) (* ListResult , error ) {
231268 o := new (ClientOptions ).defaults (c .options )
232269
233270 for _ , doer := range opts {
@@ -237,25 +274,33 @@ func (c *Client) List(ctx context.Context, prefix string, opts ...ClientOption)
237274 resp , err := c .cli .ListObjectsV2 (
238275 ctx ,
239276 & s3.ListObjectsV2Input {
240- Bucket : aws .String (o .BucketName ),
241- Prefix : aws .String (prefix ),
242-
243- MaxKeys : o .MaxKeys ,
244- StartAfter : o .StartAfter ,
277+ Bucket : aws .String (o .BucketName ),
278+ Delimiter : o .Delimiter ,
279+ Prefix : o .Prefix ,
280+ MaxKeys : o .MaxKeys ,
281+ ContinuationToken : o .PaginationToken ,
282+ StartAfter : o .StartAfter ,
245283 },
246284 o .S3Options ... ,
247285 )
248286
249287 if err != nil {
250- return nil , fmt .Errorf ("simplestorage: can't list %s/%s : %v" , o .BucketName , prefix , err )
288+ return nil , fmt .Errorf ("simplestorage: can't list %s: %v" , o .BucketName , err )
251289 }
252290
253- var result []Object
291+ result := & ListResult {
292+ Items : make ([]Object , 0 , len (resp .Contents )),
293+ HasMore : lower (resp .IsTruncated , false ),
294+ }
295+
296+ if resp .NextContinuationToken != nil {
297+ result .NextToken = * resp .NextContinuationToken
298+ }
254299
255300 for _ , obj := range resp .Contents {
256- result = append (result , Object {
301+ result . Items = append (result . Items , Object {
257302 Bucket : o .BucketName ,
258- Key : * obj .Key ,
303+ Key : lower ( obj .Key , "" ) ,
259304 Etag : lower (obj .ETag , "" ),
260305 Size : lower (obj .Size , 0 ),
261306 LastModified : lower (obj .LastModified , time.Time {}),
0 commit comments