package handler import ( "net/http" "strconv" "time" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware" ) const maxBucketList = 10000 // ListBucketsHandler handles bucket listing requests. func (h *handler) ListBucketsHandler(w http.ResponseWriter, r *http.Request) { ctx := r.Context() reqInfo := middleware.GetReqInfo(ctx) params, err := parseListBucketParams(r) if err != nil { h.logAndSendError(ctx, w, "failed to parse params", reqInfo, err) return } resp, err := h.obj.ListBuckets(ctx, params) if err != nil { h.logAndSendError(ctx, w, "something went wrong", reqInfo, err) return } if err = middleware.EncodeToResponse(w, encodeListBuckets(reqInfo.User, resp, params)); err != nil { h.logAndSendError(ctx, w, "something went wrong", reqInfo, err) } } func encodeListBuckets(owner string, resp layer.ListBucketsResult, params layer.ListBucketsParams) *ListBucketsResponse { res := &ListBucketsResponse{ Owner: Owner{ ID: owner, DisplayName: owner, }, ContinuationToken: resp.ContinuationToken, Prefix: params.Prefix, } for _, item := range resp.Containers { res.Buckets.Buckets = append(res.Buckets.Buckets, Bucket{ Name: item.Name, CreationDate: item.Created.UTC().Format(time.RFC3339), BucketRegion: item.LocationConstraint, }) } return res } func parseListBucketParams(r *http.Request) (prm layer.ListBucketsParams, err error) { prm.MaxBuckets = maxBucketList strMaxBuckets := r.URL.Query().Get(middleware.QueryMaxBuckets) if strMaxBuckets != "" { if prm.MaxBuckets, err = strconv.Atoi(strMaxBuckets); err != nil || prm.MaxBuckets < 0 { return layer.ListBucketsParams{}, errors.GetAPIError(errors.ErrInvalidMaxKeys) } } prm.Prefix = r.URL.Query().Get(middleware.QueryPrefix) prm.BucketRegion = r.URL.Query().Get(middleware.QueryBucketRegion) prm.ContinuationToken = r.URL.Query().Get(middleware.QueryContinuationToken) return }