func()

in lib/backend/s3backend/client.go [233:299]


func (c *Client) List(prefix string, opts ...backend.ListOption) (*backend.ListResult, error) {
	// For whatever reason, the S3 list API does not accept an absolute path
	// for prefix. Thus, the root is stripped from the input and added manually
	// to each output key.
	options := backend.DefaultListOptions()
	for _, opt := range opts {
		opt(options)
	}

	// If paginiated is enabled use the maximum number of keys requests from thhe options,
	// otherwise fall back to the configuration's max keys
	maxKeys := int64(c.config.ListMaxKeys)
	var continuationToken *string
	if options.Paginated {
		maxKeys = int64(options.MaxKeys)
		// An empty continuationToken should be left as nil when sending paginated list
		// requests to s3
		if options.ContinuationToken != "" {
			continuationToken = aws.String(options.ContinuationToken)
		}
	}

	var names []string
	nextContinuationToken := ""
	err := c.s3.ListObjectsV2Pages(&s3.ListObjectsV2Input{
		Bucket:            aws.String(c.config.Bucket),
		MaxKeys:           aws.Int64(maxKeys),
		Prefix:            aws.String(path.Join(c.pather.BasePath(), prefix)[1:]),
		ContinuationToken: continuationToken,
	}, func(page *s3.ListObjectsV2Output, last bool) bool {
		for _, object := range page.Contents {
			if object.Key == nil {
				log.With(
					"prefix", prefix,
					"object", object).Error("List encountered nil S3 object key")
				continue
			}
			name, err := c.pather.NameFromBlobPath(path.Join("/", *object.Key))
			if err != nil {
				log.With("key", *object.Key).Errorf("Error converting blob path into name: %s", err)
				continue
			}
			names = append(names, name)
		}

		if int64(len(names)) < maxKeys {
			// Continue iterating pages to get more keys
			return true
		}

		// Attempt to capture the continuation token before we stop iterating pages
		if page.IsTruncated != nil && *page.IsTruncated && page.NextContinuationToken != nil {
			nextContinuationToken = *page.NextContinuationToken
		}

		return false
	})

	if err != nil {
		return nil, err
	}

	return &backend.ListResult{
		Names:             names,
		ContinuationToken: nextContinuationToken,
	}, nil
}