diff --git a/api/handler/util.go b/api/handler/util.go index 3b352e8e..af595c74 100644 --- a/api/handler/util.go +++ b/api/handler/util.go @@ -15,6 +15,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware" frosterrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" @@ -78,6 +79,10 @@ func (h *handler) ResolveBucket(ctx context.Context, bucket string) (*data.Bucke return h.obj.GetBucketInfo(ctx, bucket) } +func (h *handler) ResolveCID(ctx context.Context, bucket string) (cid.ID, error) { + return h.obj.ResolveCID(ctx, bucket) +} + func (h *handler) getBucketAndCheckOwner(r *http.Request, bucket string, header ...string) (*data.BucketInfo, error) { bktInfo, err := h.obj.GetBucketInfo(r.Context(), bucket) if err != nil { diff --git a/api/layer/layer.go b/api/layer/layer.go index f44fc3f3..9879ecfe 100644 --- a/api/layer/layer.go +++ b/api/layer/layer.go @@ -234,6 +234,7 @@ type ( ListBuckets(ctx context.Context) ([]*data.BucketInfo, error) GetBucketInfo(ctx context.Context, name string) (*data.BucketInfo, error) + ResolveCID(ctx context.Context, name string) (cid.ID, error) GetBucketACL(ctx context.Context, bktInfo *data.BucketInfo) (*BucketACL, error) PutBucketACL(ctx context.Context, p *PutBucketACLParams) error CreateBucket(ctx context.Context, p *CreateBucketParams) (*data.BucketInfo, error) @@ -421,6 +422,23 @@ func (n *layer) GetBucketInfo(ctx context.Context, name string) (*data.BucketInf return n.containerInfo(ctx, containerID) } +// ResolveCID returns container id by name. +func (n *layer) ResolveCID(ctx context.Context, name string) (cid.ID, error) { + name, err := url.QueryUnescape(name) + if err != nil { + return cid.ID{}, fmt.Errorf("unescape bucket name: %w", err) + } + + reqInfo := middleware.GetReqInfo(ctx) + zone, _ := n.features.FormContainerZone(reqInfo.Namespace) + + if bktInfo := n.cache.GetBucket(zone, name); bktInfo != nil { + return bktInfo.CID, nil + } + + return n.ResolveBucket(ctx, name) +} + // GetBucketACL returns bucket acl info by name. func (n *layer) GetBucketACL(ctx context.Context, bktInfo *data.BucketInfo) (*BucketACL, error) { eACL, err := n.GetContainerEACL(ctx, bktInfo.CID) diff --git a/api/middleware/metrics.go b/api/middleware/metrics.go index 0a956126..c72c59d0 100644 --- a/api/middleware/metrics.go +++ b/api/middleware/metrics.go @@ -9,9 +9,9 @@ import ( "sync/atomic" "time" - "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/metrics" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.uber.org/zap" ) @@ -38,8 +38,8 @@ type ( ResolveNamespaceAlias(namespace string) string } - // BucketResolveFunc is a func to resolve bucket info by name. - BucketResolveFunc func(ctx context.Context, bucket string) (*data.BucketInfo, error) + // ContainerIDResolveFunc is a func to resolve container id by name. + ContainerIDResolveFunc func(ctx context.Context, bucket string) (cid.ID, error) // cidResolveFunc is a func to resolve CID in Stats handler. cidResolveFunc func(ctx context.Context, reqInfo *ReqInfo) (cnrID string) @@ -48,7 +48,7 @@ type ( const systemPath = "/system" // Metrics wraps http handler for api with basic statistics collection. -func Metrics(log *zap.Logger, resolveBucket BucketResolveFunc, appMetrics *metrics.AppMetrics, settings MetricsSettings) Func { +func Metrics(log *zap.Logger, resolveBucket ContainerIDResolveFunc, appMetrics *metrics.AppMetrics, settings MetricsSettings) Func { return func(h http.Handler) http.Handler { return stats(h.ServeHTTP, resolveCID(log, resolveBucket), appMetrics, settings) } @@ -131,19 +131,19 @@ func requestTypeFromAPI(api string) metrics.RequestType { } // resolveCID forms CIDResolveFunc using BucketResolveFunc. -func resolveCID(log *zap.Logger, resolveBucket BucketResolveFunc) cidResolveFunc { +func resolveCID(log *zap.Logger, resolveContainerID ContainerIDResolveFunc) cidResolveFunc { return func(ctx context.Context, reqInfo *ReqInfo) (cnrID string) { if reqInfo.BucketName == "" || reqInfo.API == CreateBucketOperation || reqInfo.API == "" { return "" } - bktInfo, err := resolveBucket(ctx, reqInfo.BucketName) + containerID, err := resolveContainerID(ctx, reqInfo.BucketName) if err != nil { reqLogOrDefault(ctx, log).Debug(logs.FailedToResolveCID, zap.Error(err)) return "" } - return bktInfo.CID.EncodeToString() + return containerID.EncodeToString() } } diff --git a/api/middleware/policy.go b/api/middleware/policy.go index 082ba3fc..bc479b56 100644 --- a/api/middleware/policy.go +++ b/api/middleware/policy.go @@ -7,6 +7,7 @@ import ( "net/http" "strings" + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" apiErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -28,6 +29,9 @@ type FrostFSIDInformer interface { GetUserGroupIDs(userHash util.Uint160) ([]string, error) } +// BucketResolveFunc is a func to resolve bucket info by name. +type BucketResolveFunc func(ctx context.Context, bucket string) (*data.BucketInfo, error) + type PolicyConfig struct { Storage engine.ChainRouter FrostfsID FrostFSIDInformer diff --git a/api/router.go b/api/router.go index 0c79f963..7e6e3490 100644 --- a/api/router.go +++ b/api/router.go @@ -10,6 +10,7 @@ import ( s3middleware "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/metrics" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" @@ -87,6 +88,7 @@ type ( ListMultipartUploadsHandler(http.ResponseWriter, *http.Request) ResolveBucket(ctx context.Context, bucket string) (*data.BucketInfo, error) + ResolveCID(ctx context.Context, bucket string) (cid.ID, error) } ) @@ -127,7 +129,7 @@ func NewRouter(cfg Config) *chi.Mux { middleware.ThrottleWithOpts(cfg.Throttle), middleware.Recoverer, s3middleware.Tracing(), - s3middleware.Metrics(cfg.Log, cfg.Handler.ResolveBucket, cfg.Metrics, cfg.MiddlewareSettings), + s3middleware.Metrics(cfg.Log, cfg.Handler.ResolveCID, cfg.Metrics, cfg.MiddlewareSettings), s3middleware.LogSuccessResponse(cfg.Log), s3middleware.Auth(cfg.Center, cfg.Log), ) diff --git a/api/router_mock_test.go b/api/router_mock_test.go index 7baa3a67..dfe5c414 100644 --- a/api/router_mock_test.go +++ b/api/router_mock_test.go @@ -12,6 +12,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" bearertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer/test" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" @@ -472,6 +473,14 @@ func (h *handlerMock) ResolveBucket(ctx context.Context, name string) (*data.Buc return bktInfo, nil } +func (h *handlerMock) ResolveCID(ctx context.Context, bucket string) (cid.ID, error) { + bktInfo, err := h.ResolveBucket(ctx, bucket) + if err != nil { + return cid.ID{}, err + } + return bktInfo.CID, nil +} + func (h *handlerMock) writeResponse(w http.ResponseWriter, resp *handlerResult) { respData, err := json.Marshal(resp) require.NoError(h.t, err)