forked from TrueCloudLab/frostfs-s3-gw
[#149] Update inner imports after moving middlewares
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
parent
83cdfbee78
commit
fc90981c03
36 changed files with 482 additions and 979 deletions
|
@ -19,6 +19,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
|
@ -244,7 +245,7 @@ func (s *statement) UnmarshalJSON(data []byte) error {
|
||||||
|
|
||||||
func (h *handler) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
reqInfo := api.GetReqInfo(ctx)
|
reqInfo := middleware.GetReqInfo(ctx)
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -258,7 +259,7 @@ func (h *handler) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, h.encodeBucketACL(ctx, bktInfo.Name, bucketACL)); err != nil {
|
if err = middleware.EncodeToResponse(w, h.encodeBucketACL(ctx, bktInfo.Name, bucketACL)); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -282,7 +283,7 @@ func (h *handler) bearerTokenIssuerKey(ctx context.Context) (*keys.PublicKey, er
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) PutBucketACLHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutBucketACLHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
key, err := h.bearerTokenIssuerKey(r.Context())
|
key, err := h.bearerTokenIssuerKey(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logAndSendError(w, "couldn't get bearer token issuer key", reqInfo, err)
|
h.logAndSendError(w, "couldn't get bearer token issuer key", reqInfo, err)
|
||||||
|
@ -367,7 +368,7 @@ func (h *handler) updateBucketACL(r *http.Request, astChild *ast, bktInfo *data.
|
||||||
|
|
||||||
func (h *handler) GetObjectACLHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetObjectACLHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
reqInfo := api.GetReqInfo(ctx)
|
reqInfo := middleware.GetReqInfo(ctx)
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -393,14 +394,14 @@ func (h *handler) GetObjectACLHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, h.encodeObjectACL(ctx, bucketACL, reqInfo.BucketName, objInfo.VersionID())); err != nil {
|
if err = middleware.EncodeToResponse(w, h.encodeObjectACL(ctx, bucketACL, reqInfo.BucketName, objInfo.VersionID())); err != nil {
|
||||||
h.logAndSendError(w, "failed to encode response", reqInfo, err)
|
h.logAndSendError(w, "failed to encode response", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
reqInfo := api.GetReqInfo(ctx)
|
reqInfo := middleware.GetReqInfo(ctx)
|
||||||
versionID := reqInfo.URL.Query().Get(api.QueryVersionID)
|
versionID := reqInfo.URL.Query().Get(api.QueryVersionID)
|
||||||
key, err := h.bearerTokenIssuerKey(ctx)
|
key, err := h.bearerTokenIssuerKey(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -476,7 +477,7 @@ func (h *handler) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetBucketPolicyHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketPolicyHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -514,7 +515,7 @@ func checkOwner(info *data.BucketInfo, owner string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||||
|
@ -1427,7 +1428,7 @@ func TestPutBucketPolicy(t *testing.T) {
|
||||||
createBucket(t, hc, bktName, box)
|
createBucket(t, hc, bktName, box)
|
||||||
|
|
||||||
w, r := prepareTestPayloadRequest(hc, bktName, "", bytes.NewReader([]byte(bktPolicy)))
|
w, r := prepareTestPayloadRequest(hc, bktName, "", bytes.NewReader([]byte(bktPolicy)))
|
||||||
ctx := context.WithValue(r.Context(), api.BoxData, box)
|
ctx := context.WithValue(r.Context(), middleware.BoxData, box)
|
||||||
r = r.WithContext(ctx)
|
r = r.WithContext(ctx)
|
||||||
hc.Handler().PutBucketPolicyHandler(w, r)
|
hc.Handler().PutBucketPolicyHandler(w, r)
|
||||||
assertStatus(hc.t, w, http.StatusOK)
|
assertStatus(hc.t, w, http.StatusOK)
|
||||||
|
@ -1449,7 +1450,7 @@ func putBucketPolicy(hc *handlerContext, bktName string, bktPolicy *bucketPolicy
|
||||||
require.NoError(hc.t, err)
|
require.NoError(hc.t, err)
|
||||||
|
|
||||||
w, r := prepareTestPayloadRequest(hc, bktName, "", bytes.NewReader(body))
|
w, r := prepareTestPayloadRequest(hc, bktName, "", bytes.NewReader(body))
|
||||||
ctx := context.WithValue(r.Context(), api.BoxData, box)
|
ctx := context.WithValue(r.Context(), middleware.BoxData, box)
|
||||||
r = r.WithContext(ctx)
|
r = r.WithContext(ctx)
|
||||||
hc.Handler().PutBucketPolicyHandler(w, r)
|
hc.Handler().PutBucketPolicyHandler(w, r)
|
||||||
assertStatus(hc.t, w, status)
|
assertStatus(hc.t, w, status)
|
||||||
|
@ -1516,7 +1517,7 @@ func createBucketAssertS3Error(hc *handlerContext, bktName string, box *accessbo
|
||||||
|
|
||||||
func createBucketBase(hc *handlerContext, bktName string, box *accessbox.Box) *httptest.ResponseRecorder {
|
func createBucketBase(hc *handlerContext, bktName string, box *accessbox.Box) *httptest.ResponseRecorder {
|
||||||
w, r := prepareTestRequest(hc, bktName, "", nil)
|
w, r := prepareTestRequest(hc, bktName, "", nil)
|
||||||
ctx := context.WithValue(r.Context(), api.BoxData, box)
|
ctx := context.WithValue(r.Context(), middleware.BoxData, box)
|
||||||
r = r.WithContext(ctx)
|
r = r.WithContext(ctx)
|
||||||
hc.Handler().CreateBucketHandler(w, r)
|
hc.Handler().CreateBucketHandler(w, r)
|
||||||
return w
|
return w
|
||||||
|
@ -1527,7 +1528,7 @@ func putBucketACL(t *testing.T, tc *handlerContext, bktName string, box *accessb
|
||||||
for key, val := range header {
|
for key, val := range header {
|
||||||
r.Header.Set(key, val)
|
r.Header.Set(key, val)
|
||||||
}
|
}
|
||||||
ctx := context.WithValue(r.Context(), api.BoxData, box)
|
ctx := context.WithValue(r.Context(), middleware.BoxData, box)
|
||||||
r = r.WithContext(ctx)
|
r = r.WithContext(ctx)
|
||||||
tc.Handler().PutBucketACLHandler(w, r)
|
tc.Handler().PutBucketACLHandler(w, r)
|
||||||
assertStatus(t, w, http.StatusOK)
|
assertStatus(t, w, http.StatusOK)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@ var validAttributes = map[string]struct{}{
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetObjectAttributesHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetObjectAttributesHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
params, err := parseGetObjectAttributeArgs(r)
|
params, err := parseGetObjectAttributeArgs(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -123,7 +124,7 @@ func (h *handler) GetObjectAttributesHandler(w http.ResponseWriter, r *http.Requ
|
||||||
}
|
}
|
||||||
|
|
||||||
writeAttributesHeaders(w.Header(), extendedInfo, bktSettings.Unversioned())
|
writeAttributesHeaders(w.Header(), extendedInfo, bktSettings.Unversioned())
|
||||||
if err = api.EncodeToResponse(w, response); err != nil {
|
if err = middleware.EncodeToResponse(w, response); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
@ -47,7 +48,7 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
sessionTokenEACL *session.Container
|
sessionTokenEACL *session.Container
|
||||||
|
|
||||||
ctx = r.Context()
|
ctx = r.Context()
|
||||||
reqInfo = api.GetReqInfo(ctx)
|
reqInfo = middleware.GetReqInfo(ctx)
|
||||||
|
|
||||||
containsACL = containsACLHeaders(r)
|
containsACL = containsACLHeaders(r)
|
||||||
)
|
)
|
||||||
|
@ -198,7 +199,7 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
dstObjInfo := extendedDstObjInfo.ObjectInfo
|
dstObjInfo := extendedDstObjInfo.ObjectInfo
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, &CopyObjectResponse{LastModified: dstObjInfo.Created.UTC().Format(time.RFC3339), ETag: dstObjInfo.HashSum}); err != nil {
|
if err = middleware.EncodeToResponse(w, &CopyObjectResponse{LastModified: dstObjInfo.Created.UTC().Format(time.RFC3339), ETag: dstObjInfo.HashSum}); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err, additional...)
|
h.logAndSendError(w, "something went wrong", reqInfo, err, additional...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -255,7 +256,7 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isCopyingToItselfForbidden(reqInfo *api.ReqInfo, srcBucket string, srcObject string, settings *data.BucketSettings, args *copyObjectArgs) bool {
|
func isCopyingToItselfForbidden(reqInfo *middleware.ReqInfo, srcBucket string, srcObject string, settings *data.BucketSettings, args *copyObjectArgs) bool {
|
||||||
if reqInfo.BucketName != srcBucket || reqInfo.ObjectName != srcObject {
|
if reqInfo.BucketName != srcBucket || reqInfo.ObjectName != srcObject {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *handler) GetBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -32,14 +33,14 @@ func (h *handler) GetBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, cors); err != nil {
|
if err = middleware.EncodeToResponse(w, cors); err != nil {
|
||||||
h.logAndSendError(w, "could not encode cors to response", reqInfo, err)
|
h.logAndSendError(w, "could not encode cors to response", reqInfo, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) PutBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -63,11 +64,11 @@ func (h *handler) PutBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
api.WriteSuccessResponseHeadersOnly(w)
|
middleware.WriteSuccessResponseHeadersOnly(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) DeleteBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) DeleteBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -92,7 +93,7 @@ func (h *handler) AppendCORSHeaders(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
reqInfo := api.GetReqInfo(ctx)
|
reqInfo := middleware.GetReqInfo(ctx)
|
||||||
if reqInfo.BucketName == "" {
|
if reqInfo.BucketName == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -143,7 +144,7 @@ func (h *handler) AppendCORSHeaders(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) Preflight(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) Preflight(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName)
|
bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logAndSendError(w, "could not get bucket info", reqInfo, err)
|
h.logAndSendError(w, "could not get bucket info", reqInfo, err)
|
||||||
|
@ -197,7 +198,7 @@ func (h *handler) Preflight(w http.ResponseWriter, r *http.Request) {
|
||||||
if o != wildcard {
|
if o != wildcard {
|
||||||
w.Header().Set(api.AccessControlAllowCredentials, "true")
|
w.Header().Set(api.AccessControlAllowCredentials, "true")
|
||||||
}
|
}
|
||||||
api.WriteSuccessResponseHeadersOnly(w)
|
middleware.WriteSuccessResponseHeadersOnly(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCORSOriginWildcard(t *testing.T) {
|
func TestCORSOriginWildcard(t *testing.T) {
|
||||||
|
@ -23,14 +24,14 @@ func TestCORSOriginWildcard(t *testing.T) {
|
||||||
bktName := "bucket-for-cors"
|
bktName := "bucket-for-cors"
|
||||||
box, _ := createAccessBox(t)
|
box, _ := createAccessBox(t)
|
||||||
w, r := prepareTestRequest(hc, bktName, "", nil)
|
w, r := prepareTestRequest(hc, bktName, "", nil)
|
||||||
ctx := context.WithValue(r.Context(), api.BoxData, box)
|
ctx := context.WithValue(r.Context(), middleware.BoxData, box)
|
||||||
r = r.WithContext(ctx)
|
r = r.WithContext(ctx)
|
||||||
r.Header.Add(api.AmzACL, "public-read")
|
r.Header.Add(api.AmzACL, "public-read")
|
||||||
hc.Handler().CreateBucketHandler(w, r)
|
hc.Handler().CreateBucketHandler(w, r)
|
||||||
assertStatus(t, w, http.StatusOK)
|
assertStatus(t, w, http.StatusOK)
|
||||||
|
|
||||||
w, r = prepareTestPayloadRequest(hc, bktName, "", strings.NewReader(body))
|
w, r = prepareTestPayloadRequest(hc, bktName, "", strings.NewReader(body))
|
||||||
ctx = context.WithValue(r.Context(), api.BoxData, box)
|
ctx = context.WithValue(r.Context(), middleware.BoxData, box)
|
||||||
r = r.WithContext(ctx)
|
r = r.WithContext(ctx)
|
||||||
hc.Handler().PutBucketCorsHandler(w, r)
|
hc.Handler().PutBucketCorsHandler(w, r)
|
||||||
assertStatus(t, w, http.StatusOK)
|
assertStatus(t, w, http.StatusOK)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||||
|
@ -62,7 +63,7 @@ type DeleteObjectsResponse struct {
|
||||||
|
|
||||||
func (h *handler) DeleteObjectHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) DeleteObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
reqInfo := api.GetReqInfo(ctx)
|
reqInfo := middleware.GetReqInfo(ctx)
|
||||||
versionID := reqInfo.URL.Query().Get(api.QueryVersionID)
|
versionID := reqInfo.URL.Query().Get(api.QueryVersionID)
|
||||||
versionedObject := []*layer.VersionedObject{{
|
versionedObject := []*layer.VersionedObject{{
|
||||||
Name: reqInfo.ObjectName,
|
Name: reqInfo.ObjectName,
|
||||||
|
@ -158,7 +159,7 @@ func isErrObjectLocked(err error) bool {
|
||||||
// DeleteMultipleObjectsHandler handles multiple delete requests.
|
// DeleteMultipleObjectsHandler handles multiple delete requests.
|
||||||
func (h *handler) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
reqInfo := api.GetReqInfo(ctx)
|
reqInfo := middleware.GetReqInfo(ctx)
|
||||||
|
|
||||||
// Content-Md5 is required and should be set
|
// Content-Md5 is required and should be set
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
|
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
|
||||||
|
@ -264,14 +265,14 @@ func (h *handler) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Re
|
||||||
h.reqLogger(ctx).Error("couldn't delete objects", fields...)
|
h.reqLogger(ctx).Error("couldn't delete objects", fields...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, response); err != nil {
|
if err = middleware.EncodeToResponse(w, response); err != nil {
|
||||||
h.logAndSendError(w, "could not write response", reqInfo, err, zap.Array("objects", marshaler))
|
h.logAndSendError(w, "could not write response", reqInfo, err, zap.Array("objects", marshaler))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) DeleteBucketHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) DeleteBucketHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logAndSendError(w, "could not get bucket info", reqInfo, err)
|
h.logAndSendError(w, "could not get bucket info", reqInfo, err)
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -117,7 +118,7 @@ func (h *handler) GetObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
params *layer.RangeParams
|
params *layer.RangeParams
|
||||||
|
|
||||||
reqInfo = api.GetReqInfo(r.Context())
|
reqInfo = middleware.GetReqInfo(r.Context())
|
||||||
)
|
)
|
||||||
|
|
||||||
conditional, err := parseConditionalHeaders(r.Header)
|
conditional, err := parseConditionalHeaders(r.Header)
|
||||||
|
|
|
@ -13,10 +13,10 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/cache"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/cache"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/resolver"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/resolver"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/tree"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/tree"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
|
@ -139,7 +139,7 @@ func prepareHandlerContextBase(t *testing.T, minCache bool) *handlerContext {
|
||||||
h: h,
|
h: h,
|
||||||
tp: tp,
|
tp: tp,
|
||||||
tree: treeMock,
|
tree: treeMock,
|
||||||
context: context.WithValue(context.Background(), api.BoxData, newTestAccessBox(t, key)),
|
context: context.WithValue(context.Background(), middleware.BoxData, newTestAccessBox(t, key)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,8 +246,8 @@ func prepareTestRequestWithQuery(hc *handlerContext, bktName, objName string, qu
|
||||||
r := httptest.NewRequest(http.MethodPut, defaultURL, bytes.NewReader(body))
|
r := httptest.NewRequest(http.MethodPut, defaultURL, bytes.NewReader(body))
|
||||||
r.URL.RawQuery = query.Encode()
|
r.URL.RawQuery = query.Encode()
|
||||||
|
|
||||||
reqInfo := api.NewReqInfo(w, r, api.ObjectRequest{Bucket: bktName, Object: objName})
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: bktName, Object: objName})
|
||||||
r = r.WithContext(api.SetReqInfo(hc.Context(), reqInfo))
|
r = r.WithContext(middleware.SetReqInfo(hc.Context(), reqInfo))
|
||||||
|
|
||||||
return w, r
|
return w, r
|
||||||
}
|
}
|
||||||
|
@ -256,8 +256,8 @@ func prepareTestPayloadRequest(hc *handlerContext, bktName, objName string, payl
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest(http.MethodPut, defaultURL, payload)
|
r := httptest.NewRequest(http.MethodPut, defaultURL, payload)
|
||||||
|
|
||||||
reqInfo := api.NewReqInfo(w, r, api.ObjectRequest{Bucket: bktName, Object: objName})
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: bktName, Object: objName})
|
||||||
r = r.WithContext(api.SetReqInfo(hc.Context(), reqInfo))
|
r = r.WithContext(middleware.SetReqInfo(hc.Context(), reqInfo))
|
||||||
|
|
||||||
return w, r
|
return w, r
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ func getRangeToDetectContentType(maxSize uint64) *layer.RangeParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) HeadObjectHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) HeadObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -114,7 +115,7 @@ func (h *handler) HeadObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) HeadBucketHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) HeadBucketHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -131,7 +132,7 @@ func (h *handler) HeadBucketHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set(api.ContainerZone, bktInfo.Zone)
|
w.Header().Set(api.ContainerZone, bktInfo.Zone)
|
||||||
}
|
}
|
||||||
|
|
||||||
api.WriteResponse(w, http.StatusOK, nil, api.MimeNone)
|
middleware.WriteResponse(w, http.StatusOK, nil, middleware.MimeNone)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) setLockingHeaders(bktInfo *data.BucketInfo, lockInfo *data.LockInfo, header http.Header) error {
|
func (h *handler) setLockingHeaders(bktInfo *data.BucketInfo, lockInfo *data.LockInfo, header http.Header) error {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
||||||
s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||||
|
@ -84,7 +85,7 @@ func TestInvalidAccessThroughCache(t *testing.T) {
|
||||||
headObject(t, tc, bktName, objName, nil, http.StatusOK)
|
headObject(t, tc, bktName, objName, nil, http.StatusOK)
|
||||||
|
|
||||||
w, r := prepareTestRequest(tc, bktName, objName, nil)
|
w, r := prepareTestRequest(tc, bktName, objName, nil)
|
||||||
tc.Handler().HeadObjectHandler(w, r.WithContext(context.WithValue(r.Context(), api.BoxData, newTestAccessBox(t, nil))))
|
tc.Handler().HeadObjectHandler(w, r.WithContext(context.WithValue(r.Context(), middleware.BoxData, newTestAccessBox(t, nil))))
|
||||||
assertStatus(t, w, http.StatusForbidden)
|
assertStatus(t, w, http.StatusForbidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ package handler
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *handler) GetBucketLocationHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketLocationHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -15,7 +15,7 @@ func (h *handler) GetBucketLocationHandler(w http.ResponseWriter, r *http.Reques
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, LocationResponse{Location: bktInfo.LocationConstraint}); err != nil {
|
if err = middleware.EncodeToResponse(w, LocationResponse{Location: bktInfo.LocationConstraint}); err != nil {
|
||||||
h.logAndSendError(w, "couldn't encode bucket location response", reqInfo, err)
|
h.logAndSendError(w, "couldn't encode bucket location response", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ func (h *handler) ListBucketsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
own user.ID
|
own user.ID
|
||||||
res *ListBucketsResponse
|
res *ListBucketsResponse
|
||||||
reqInfo = api.GetReqInfo(r.Context())
|
reqInfo = middleware.GetReqInfo(r.Context())
|
||||||
)
|
)
|
||||||
|
|
||||||
list, err := h.obj.ListBuckets(r.Context())
|
list, err := h.obj.ListBuckets(r.Context())
|
||||||
|
@ -42,7 +42,7 @@ func (h *handler) ListBucketsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, res); err != nil {
|
if err = middleware.EncodeToResponse(w, res); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
apiErrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
apiErrors "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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -26,7 +27,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *handler) PutBucketObjectLockConfigHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutBucketObjectLockConfigHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -73,7 +74,7 @@ func (h *handler) PutBucketObjectLockConfigHandler(w http.ResponseWriter, r *htt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetBucketObjectLockConfigHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketObjectLockConfigHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -100,13 +101,13 @@ func (h *handler) GetBucketObjectLockConfigHandler(w http.ResponseWriter, r *htt
|
||||||
settings.LockConfiguration.ObjectLockEnabled = enabledValue
|
settings.LockConfiguration.ObjectLockEnabled = enabledValue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, settings.LockConfiguration); err != nil {
|
if err = middleware.EncodeToResponse(w, settings.LockConfiguration); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) PutObjectLegalHoldHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutObjectLegalHoldHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -158,7 +159,7 @@ func (h *handler) PutObjectLegalHoldHandler(w http.ResponseWriter, r *http.Reque
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetObjectLegalHoldHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetObjectLegalHoldHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -189,13 +190,13 @@ func (h *handler) GetObjectLegalHoldHandler(w http.ResponseWriter, r *http.Reque
|
||||||
legalHold.Status = legalHoldOn
|
legalHold.Status = legalHoldOn
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, legalHold); err != nil {
|
if err = middleware.EncodeToResponse(w, legalHold); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) PutObjectRetentionHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutObjectRetentionHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -242,7 +243,7 @@ func (h *handler) PutObjectRetentionHandler(w http.ResponseWriter, r *http.Reque
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetObjectRetentionHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetObjectRetentionHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -281,7 +282,7 @@ func (h *handler) GetObjectRetentionHandler(w http.ResponseWriter, r *http.Reque
|
||||||
retention.Mode = complianceMode
|
retention.Mode = complianceMode
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, retention); err != nil {
|
if err = middleware.EncodeToResponse(w, retention); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
apiErrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
apiErrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -313,7 +314,7 @@ func TestPutBucketLockConfigurationHandler(t *testing.T) {
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest(http.MethodPut, defaultURL, bytes.NewReader(body))
|
r := httptest.NewRequest(http.MethodPut, defaultURL, bytes.NewReader(body))
|
||||||
r = r.WithContext(api.SetReqInfo(r.Context(), api.NewReqInfo(w, r, api.ObjectRequest{Bucket: tc.bucket})))
|
r = r.WithContext(middleware.SetReqInfo(r.Context(), middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: tc.bucket})))
|
||||||
|
|
||||||
hc.Handler().PutBucketObjectLockConfigHandler(w, r)
|
hc.Handler().PutBucketObjectLockConfigHandler(w, r)
|
||||||
|
|
||||||
|
@ -386,7 +387,7 @@ func TestGetBucketLockConfigurationHandler(t *testing.T) {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest(http.MethodPut, defaultURL, bytes.NewReader(nil))
|
r := httptest.NewRequest(http.MethodPut, defaultURL, bytes.NewReader(nil))
|
||||||
r = r.WithContext(api.SetReqInfo(r.Context(), api.NewReqInfo(w, r, api.ObjectRequest{Bucket: tc.bucket})))
|
r = r.WithContext(middleware.SetReqInfo(r.Context(), middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: tc.bucket})))
|
||||||
|
|
||||||
hc.Handler().GetBucketObjectLockConfigHandler(w, r)
|
hc.Handler().GetBucketObjectLockConfigHandler(w, r)
|
||||||
|
|
||||||
|
@ -406,7 +407,7 @@ func TestGetBucketLockConfigurationHandler(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertS3Error(t *testing.T, w *httptest.ResponseRecorder, expectedError apiErrors.Error) {
|
func assertS3Error(t *testing.T, w *httptest.ResponseRecorder, expectedError apiErrors.Error) {
|
||||||
actualErrorResponse := &api.ErrorResponse{}
|
actualErrorResponse := &middleware.ErrorResponse{}
|
||||||
err := xml.NewDecoder(w.Result().Body).Decode(actualErrorResponse)
|
err := xml.NewDecoder(w.Result().Body).Decode(actualErrorResponse)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
@ -94,7 +95,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *handler) CreateMultipartUploadHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) CreateMultipartUploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -170,7 +171,7 @@ func (h *handler) CreateMultipartUploadHandler(w http.ResponseWriter, r *http.Re
|
||||||
UploadID: uploadID.String(),
|
UploadID: uploadID.String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, resp); err != nil {
|
if err = middleware.EncodeToResponse(w, resp); err != nil {
|
||||||
h.logAndSendError(w, "could not encode InitiateMultipartUploadResponse to response", reqInfo, err, additional...)
|
h.logAndSendError(w, "could not encode InitiateMultipartUploadResponse to response", reqInfo, err, additional...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -196,7 +197,7 @@ func formACLHeadersForMultipart(header http.Header) map[string]string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) UploadPartHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) UploadPartHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -270,14 +271,14 @@ func (h *handler) UploadPartHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set(api.ETag, hash)
|
w.Header().Set(api.ETag, hash)
|
||||||
api.WriteSuccessResponseHeadersOnly(w)
|
middleware.WriteSuccessResponseHeadersOnly(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) UploadPartCopy(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) UploadPartCopy(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
versionID string
|
versionID string
|
||||||
ctx = r.Context()
|
ctx = r.Context()
|
||||||
reqInfo = api.GetReqInfo(ctx)
|
reqInfo = middleware.GetReqInfo(ctx)
|
||||||
queryValues = reqInfo.URL.Query()
|
queryValues = reqInfo.URL.Query()
|
||||||
uploadID = queryValues.Get(uploadIDHeaderName)
|
uploadID = queryValues.Get(uploadIDHeaderName)
|
||||||
additional = []zap.Field{zap.String("uploadID", uploadID), zap.String("Key", reqInfo.ObjectName)}
|
additional = []zap.Field{zap.String("uploadID", uploadID), zap.String("Key", reqInfo.ObjectName)}
|
||||||
|
@ -385,13 +386,13 @@ func (h *handler) UploadPartCopy(w http.ResponseWriter, r *http.Request) {
|
||||||
addSSECHeaders(w.Header(), r.Header)
|
addSSECHeaders(w.Header(), r.Header)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, response); err != nil {
|
if err = middleware.EncodeToResponse(w, response); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -438,11 +439,11 @@ func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.
|
||||||
// successfully or not.
|
// successfully or not.
|
||||||
headerIsWritten := stopPeriodicResponseWriter()
|
headerIsWritten := stopPeriodicResponseWriter()
|
||||||
|
|
||||||
responseWriter := api.EncodeToResponse
|
responseWriter := middleware.EncodeToResponse
|
||||||
errLogger := h.logAndSendError
|
errLogger := h.logAndSendError
|
||||||
// Do not send XML and HTTP headers if periodic writer was invoked at this point.
|
// Do not send XML and HTTP headers if periodic writer was invoked at this point.
|
||||||
if headerIsWritten {
|
if headerIsWritten {
|
||||||
responseWriter = api.EncodeToResponseNoHeader
|
responseWriter = middleware.EncodeToResponseNoHeader
|
||||||
errLogger = h.logAndSendErrorNoHeader
|
errLogger = h.logAndSendErrorNoHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,7 +467,7 @@ func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) completeMultipartUpload(r *http.Request, c *layer.CompleteMultipartParams, bktInfo *data.BucketInfo, reqInfo *api.ReqInfo) (*data.ObjectInfo, error) {
|
func (h *handler) completeMultipartUpload(r *http.Request, c *layer.CompleteMultipartParams, bktInfo *data.BucketInfo, reqInfo *middleware.ReqInfo) (*data.ObjectInfo, error) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
uploadData, extendedObjInfo, err := h.obj.CompleteMultipartUpload(ctx, c)
|
uploadData, extendedObjInfo, err := h.obj.CompleteMultipartUpload(ctx, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -530,7 +531,7 @@ func (h *handler) completeMultipartUpload(r *http.Request, c *layer.CompleteMult
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) ListMultipartUploadsHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ListMultipartUploadsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -572,13 +573,13 @@ func (h *handler) ListMultipartUploadsHandler(w http.ResponseWriter, r *http.Req
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, encodeListMultipartUploadsToResponse(list, p)); err != nil {
|
if err = middleware.EncodeToResponse(w, encodeListMultipartUploadsToResponse(list, p)); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) ListPartsHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ListPartsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -635,13 +636,13 @@ func (h *handler) ListPartsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, encodeListPartsToResponse(list, p)); err != nil {
|
if err = middleware.EncodeToResponse(w, encodeListPartsToResponse(list, p)); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) AbortMultipartUploadHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) AbortMultipartUploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -3,18 +3,18 @@ package handler
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *handler) DeleteBucketPolicyHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) DeleteBucketPolicyHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not supported", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotSupported))
|
h.logAndSendError(w, "not supported", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotSupported))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) DeleteBucketLifecycleHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) DeleteBucketLifecycleHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not supported", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotSupported))
|
h.logAndSendError(w, "not supported", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotSupported))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) DeleteBucketEncryptionHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) DeleteBucketEncryptionHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not supported", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotSupported))
|
h.logAndSendError(w, "not supported", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotSupported))
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
@ -21,7 +21,7 @@ type (
|
||||||
Event string
|
Event string
|
||||||
NotificationInfo *data.NotificationInfo
|
NotificationInfo *data.NotificationInfo
|
||||||
BktInfo *data.BucketInfo
|
BktInfo *data.BucketInfo
|
||||||
ReqInfo *api.ReqInfo
|
ReqInfo *middleware.ReqInfo
|
||||||
User string
|
User string
|
||||||
Time time.Time
|
Time time.Time
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ var validEvents = map[string]struct{}{
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) PutBucketNotificationHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutBucketNotificationHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logAndSendError(w, "could not get bucket info", reqInfo, err)
|
h.logAndSendError(w, "could not get bucket info", reqInfo, err)
|
||||||
|
@ -133,7 +133,7 @@ func (h *handler) PutBucketNotificationHandler(w http.ResponseWriter, r *http.Re
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetBucketNotificationHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketNotificationHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -147,7 +147,7 @@ func (h *handler) GetBucketNotificationHandler(w http.ResponseWriter, r *http.Re
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, conf); err != nil {
|
if err = middleware.EncodeToResponse(w, conf); err != nil {
|
||||||
h.logAndSendError(w, "could not encode bucket notification configuration to response", reqInfo, err)
|
h.logAndSendError(w, "could not encode bucket notification configuration to response", reqInfo, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ func (h *handler) sendNotifications(ctx context.Context, p *SendNotificationPara
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkBucketConfiguration checks notification configuration and generates an ID for configurations with empty ids.
|
// checkBucketConfiguration checks notification configuration and generates an ID for configurations with empty ids.
|
||||||
func (h *handler) checkBucketConfiguration(ctx context.Context, conf *data.NotificationConfiguration, r *api.ReqInfo) (completed bool, err error) {
|
func (h *handler) checkBucketConfiguration(ctx context.Context, conf *data.NotificationConfiguration, r *middleware.ReqInfo) (completed bool, err error) {
|
||||||
if conf == nil {
|
if conf == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,16 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListObjectsV1Handler handles objects listing requests for API version 1.
|
// ListObjectsV1Handler handles objects listing requests for API version 1.
|
||||||
func (h *handler) ListObjectsV1Handler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ListObjectsV1Handler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
params, err := parseListObjectsArgsV1(reqInfo)
|
params, err := parseListObjectsArgsV1(reqInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logAndSendError(w, "failed to parse arguments", reqInfo, err)
|
h.logAndSendError(w, "failed to parse arguments", reqInfo, err)
|
||||||
|
@ -33,7 +33,7 @@ func (h *handler) ListObjectsV1Handler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, encodeV1(params, list)); err != nil {
|
if err = middleware.EncodeToResponse(w, encodeV1(params, list)); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ func encodeV1(p *layer.ListObjectsParamsV1, list *layer.ListObjectsInfoV1) *List
|
||||||
|
|
||||||
// ListObjectsV2Handler handles objects listing requests for API version 2.
|
// ListObjectsV2Handler handles objects listing requests for API version 2.
|
||||||
func (h *handler) ListObjectsV2Handler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ListObjectsV2Handler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
params, err := parseListObjectsArgsV2(reqInfo)
|
params, err := parseListObjectsArgsV2(reqInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logAndSendError(w, "failed to parse arguments", reqInfo, err)
|
h.logAndSendError(w, "failed to parse arguments", reqInfo, err)
|
||||||
|
@ -77,7 +77,7 @@ func (h *handler) ListObjectsV2Handler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, encodeV2(params, list)); err != nil {
|
if err = middleware.EncodeToResponse(w, encodeV2(params, list)); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ func encodeV2(p *layer.ListObjectsParamsV2, list *layer.ListObjectsInfoV2) *List
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseListObjectsArgsV1(reqInfo *api.ReqInfo) (*layer.ListObjectsParamsV1, error) {
|
func parseListObjectsArgsV1(reqInfo *middleware.ReqInfo) (*layer.ListObjectsParamsV1, error) {
|
||||||
var (
|
var (
|
||||||
res layer.ListObjectsParamsV1
|
res layer.ListObjectsParamsV1
|
||||||
queryValues = reqInfo.URL.Query()
|
queryValues = reqInfo.URL.Query()
|
||||||
|
@ -120,7 +120,7 @@ func parseListObjectsArgsV1(reqInfo *api.ReqInfo) (*layer.ListObjectsParamsV1, e
|
||||||
return &res, nil
|
return &res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseListObjectsArgsV2(reqInfo *api.ReqInfo) (*layer.ListObjectsParamsV2, error) {
|
func parseListObjectsArgsV2(reqInfo *middleware.ReqInfo) (*layer.ListObjectsParamsV2, error) {
|
||||||
var (
|
var (
|
||||||
res layer.ListObjectsParamsV2
|
res layer.ListObjectsParamsV2
|
||||||
queryValues = reqInfo.URL.Query()
|
queryValues = reqInfo.URL.Query()
|
||||||
|
@ -142,7 +142,7 @@ func parseListObjectsArgsV2(reqInfo *api.ReqInfo) (*layer.ListObjectsParamsV2, e
|
||||||
return &res, nil
|
return &res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseListObjectArgs(reqInfo *api.ReqInfo) (*layer.ListObjectsParamsCommon, error) {
|
func parseListObjectArgs(reqInfo *middleware.ReqInfo) (*layer.ListObjectsParamsCommon, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
res layer.ListObjectsParamsCommon
|
res layer.ListObjectsParamsCommon
|
||||||
|
@ -211,7 +211,7 @@ func fillContents(src []*data.ObjectInfo, encode string, fetchOwner bool) []Obje
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) ListBucketObjectVersionsHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ListBucketObjectVersionsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
p, err := parseListObjectVersionsRequest(reqInfo)
|
p, err := parseListObjectVersionsRequest(reqInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logAndSendError(w, "failed to parse request", reqInfo, err)
|
h.logAndSendError(w, "failed to parse request", reqInfo, err)
|
||||||
|
@ -230,12 +230,12 @@ func (h *handler) ListBucketObjectVersionsHandler(w http.ResponseWriter, r *http
|
||||||
}
|
}
|
||||||
|
|
||||||
response := encodeListObjectVersionsToResponse(info, p.BktInfo.Name)
|
response := encodeListObjectVersionsToResponse(info, p.BktInfo.Name)
|
||||||
if err = api.EncodeToResponse(w, response); err != nil {
|
if err = middleware.EncodeToResponse(w, response); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseListObjectVersionsRequest(reqInfo *api.ReqInfo) (*layer.ListObjectVersionsParams, error) {
|
func parseListObjectVersionsRequest(reqInfo *middleware.ReqInfo) (*layer.ListObjectVersionsParams, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
res layer.ListObjectVersionsParams
|
res layer.ListObjectVersionsParams
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/encryption"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/encryption"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||||
|
@ -180,7 +181,7 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
sessionTokenEACL *session.Container
|
sessionTokenEACL *session.Container
|
||||||
containsACL = containsACLHeaders(r)
|
containsACL = containsACLHeaders(r)
|
||||||
ctx = r.Context()
|
ctx = r.Context()
|
||||||
reqInfo = api.GetReqInfo(ctx)
|
reqInfo = middleware.GetReqInfo(ctx)
|
||||||
)
|
)
|
||||||
|
|
||||||
if containsACL {
|
if containsACL {
|
||||||
|
@ -335,7 +336,7 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set(api.ETag, objInfo.HashSum)
|
w.Header().Set(api.ETag, objInfo.HashSum)
|
||||||
api.WriteSuccessResponseHeadersOnly(w)
|
middleware.WriteSuccessResponseHeadersOnly(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func formEncryptionParams(r *http.Request) (enc encryption.Params, err error) {
|
func formEncryptionParams(r *http.Request) (enc encryption.Params, err error) {
|
||||||
|
@ -388,7 +389,7 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
||||||
tagSet map[string]string
|
tagSet map[string]string
|
||||||
sessionTokenEACL *session.Container
|
sessionTokenEACL *session.Container
|
||||||
ctx = r.Context()
|
ctx = r.Context()
|
||||||
reqInfo = api.GetReqInfo(ctx)
|
reqInfo = middleware.GetReqInfo(ctx)
|
||||||
metadata = make(map[string]string)
|
metadata = make(map[string]string)
|
||||||
containsACL = containsACLHeaders(r)
|
containsACL = containsACLHeaders(r)
|
||||||
)
|
)
|
||||||
|
@ -530,7 +531,7 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
||||||
ETag: objInfo.HashSum,
|
ETag: objInfo.HashSum,
|
||||||
}
|
}
|
||||||
w.WriteHeader(status)
|
w.WriteHeader(status)
|
||||||
if _, err = w.Write(api.EncodeResponse(resp)); err != nil {
|
if _, err = w.Write(middleware.EncodeResponse(resp)); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -541,7 +542,7 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(status)
|
w.WriteHeader(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPostPolicy(r *http.Request, reqInfo *api.ReqInfo, metadata map[string]string) (*postPolicy, error) {
|
func checkPostPolicy(r *http.Request, reqInfo *middleware.ReqInfo, metadata map[string]string) (*postPolicy, error) {
|
||||||
policy := &postPolicy{empty: true}
|
policy := &postPolicy{empty: true}
|
||||||
if policyStr := auth.MultipartFormValue(r, "policy"); policyStr != "" {
|
if policyStr := auth.MultipartFormValue(r, "policy"); policyStr != "" {
|
||||||
policyData, err := base64.StdEncoding.DecodeString(policyStr)
|
policyData, err := base64.StdEncoding.DecodeString(policyStr)
|
||||||
|
@ -681,7 +682,7 @@ func parseMetadata(r *http.Request) map[string]string {
|
||||||
|
|
||||||
func (h *handler) CreateBucketHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) CreateBucketHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
reqInfo := api.GetReqInfo(ctx)
|
reqInfo := middleware.GetReqInfo(ctx)
|
||||||
p := &layer.CreateBucketParams{
|
p := &layer.CreateBucketParams{
|
||||||
Name: reqInfo.BucketName,
|
Name: reqInfo.BucketName,
|
||||||
}
|
}
|
||||||
|
@ -761,7 +762,7 @@ func (h *handler) CreateBucketHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
api.WriteSuccessResponseHeadersOnly(w)
|
middleware.WriteSuccessResponseHeadersOnly(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h handler) setPolicy(prm *layer.CreateBucketParams, locationConstraint string, userPolicies []*accessbox.ContainerPolicy) error {
|
func (h handler) setPolicy(prm *layer.CreateBucketParams, locationConstraint string, userPolicies []*accessbox.ContainerPolicy) error {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
v4 "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/v4"
|
v4 "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/v4"
|
||||||
s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
s3errors "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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -110,7 +111,7 @@ func TestEmptyPostPolicy(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
reqInfo := &api.ReqInfo{}
|
reqInfo := &middleware.ReqInfo{}
|
||||||
metadata := make(map[string]string)
|
metadata := make(map[string]string)
|
||||||
|
|
||||||
_, err := checkPostPolicy(r, reqInfo, metadata)
|
_, err := checkPostPolicy(r, reqInfo, metadata)
|
||||||
|
@ -217,16 +218,16 @@ func TestPutObjectWithStreamBodyAWSExample(t *testing.T) {
|
||||||
req.Body = io.NopCloser(reqBody)
|
req.Body = io.NopCloser(reqBody)
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
reqInfo := api.NewReqInfo(w, req, api.ObjectRequest{Bucket: bktName, Object: objName})
|
reqInfo := middleware.NewReqInfo(w, req, middleware.ObjectRequest{Bucket: bktName, Object: objName})
|
||||||
req = req.WithContext(api.SetReqInfo(tc.Context(), reqInfo))
|
req = req.WithContext(middleware.SetReqInfo(tc.Context(), reqInfo))
|
||||||
req = req.WithContext(context.WithValue(req.Context(), api.ClientTime, signTime))
|
req = req.WithContext(context.WithValue(req.Context(), middleware.ClientTime, signTime))
|
||||||
req = req.WithContext(context.WithValue(req.Context(), api.AuthHeaders, &auth.AuthHeader{
|
req = req.WithContext(context.WithValue(req.Context(), middleware.AuthHeaders, &auth.AuthHeader{
|
||||||
AccessKeyID: AWSAccessKeyID,
|
AccessKeyID: AWSAccessKeyID,
|
||||||
SignatureV4: "4f232c4386841ef735655705268965c44a0e4690baa4adea153f7db9fa80a0a9",
|
SignatureV4: "4f232c4386841ef735655705268965c44a0e4690baa4adea153f7db9fa80a0a9",
|
||||||
Service: "s3",
|
Service: "s3",
|
||||||
Region: "us-east-1",
|
Region: "us-east-1",
|
||||||
}))
|
}))
|
||||||
req = req.WithContext(context.WithValue(req.Context(), api.BoxData, &accessbox.Box{
|
req = req.WithContext(context.WithValue(req.Context(), middleware.BoxData, &accessbox.Box{
|
||||||
Gate: &accessbox.GateData{
|
Gate: &accessbox.GateData{
|
||||||
AccessKey: AWSSecretAccessKey,
|
AccessKey: AWSSecretAccessKey,
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,10 +9,10 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth"
|
||||||
v4 "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/v4"
|
v4 "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/v4"
|
||||||
errs "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
errs "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
)
|
)
|
||||||
|
@ -193,12 +193,12 @@ func (c *s3ChunkReader) Read(buf []byte) (num int, err error) {
|
||||||
func newSignV4ChunkedReader(req *http.Request) (io.ReadCloser, error) {
|
func newSignV4ChunkedReader(req *http.Request) (io.ReadCloser, error) {
|
||||||
// Expecting to refactor this in future:
|
// Expecting to refactor this in future:
|
||||||
// https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/issues/137
|
// https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/issues/137
|
||||||
box, ok := req.Context().Value(api.BoxData).(*accessbox.Box)
|
box, ok := req.Context().Value(middleware.BoxData).(*accessbox.Box)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errs.GetAPIError(errs.ErrAuthorizationHeaderMalformed)
|
return nil, errs.GetAPIError(errs.ErrAuthorizationHeaderMalformed)
|
||||||
}
|
}
|
||||||
|
|
||||||
authHeaders, ok := req.Context().Value(api.AuthHeaders).(*auth.AuthHeader)
|
authHeaders, ok := req.Context().Value(middleware.AuthHeaders).(*auth.AuthHeader)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errs.GetAPIError(errs.ErrAuthorizationHeaderMalformed)
|
return nil, errs.GetAPIError(errs.ErrAuthorizationHeaderMalformed)
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ func newSignV4ChunkedReader(req *http.Request) (io.ReadCloser, error) {
|
||||||
return nil, errs.GetAPIError(errs.ErrSignatureDoesNotMatch)
|
return nil, errs.GetAPIError(errs.ErrSignatureDoesNotMatch)
|
||||||
}
|
}
|
||||||
|
|
||||||
reqTime, ok := req.Context().Value(api.ClientTime).(time.Time)
|
reqTime, ok := req.Context().Value(middleware.ClientTime).(time.Time)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errs.GetAPIError(errs.ErrMalformedDate)
|
return nil, errs.GetAPIError(errs.ErrMalformedDate)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ const (
|
||||||
|
|
||||||
func (h *handler) PutObjectTaggingHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutObjectTaggingHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
reqInfo := api.GetReqInfo(ctx)
|
reqInfo := middleware.GetReqInfo(ctx)
|
||||||
|
|
||||||
tagSet, err := readTagSet(r.Body)
|
tagSet, err := readTagSet(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -72,7 +73,7 @@ func (h *handler) PutObjectTaggingHandler(w http.ResponseWriter, r *http.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetObjectTaggingHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetObjectTaggingHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -103,14 +104,14 @@ func (h *handler) GetObjectTaggingHandler(w http.ResponseWriter, r *http.Request
|
||||||
if settings.VersioningEnabled() {
|
if settings.VersioningEnabled() {
|
||||||
w.Header().Set(api.AmzVersionID, versionID)
|
w.Header().Set(api.AmzVersionID, versionID)
|
||||||
}
|
}
|
||||||
if err = api.EncodeToResponse(w, encodeTagging(tagSet)); err != nil {
|
if err = middleware.EncodeToResponse(w, encodeTagging(tagSet)); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) DeleteObjectTaggingHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) DeleteObjectTaggingHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
reqInfo := api.GetReqInfo(ctx)
|
reqInfo := middleware.GetReqInfo(ctx)
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -149,7 +150,7 @@ func (h *handler) DeleteObjectTaggingHandler(w http.ResponseWriter, r *http.Requ
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) PutBucketTaggingHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutBucketTaggingHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
tagSet, err := readTagSet(r.Body)
|
tagSet, err := readTagSet(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -170,7 +171,7 @@ func (h *handler) PutBucketTaggingHandler(w http.ResponseWriter, r *http.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetBucketTaggingHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketTaggingHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -184,14 +185,14 @@ func (h *handler) GetBucketTaggingHandler(w http.ResponseWriter, r *http.Request
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, encodeTagging(tagSet)); err != nil {
|
if err = middleware.EncodeToResponse(w, encodeTagging(tagSet)); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) DeleteBucketTaggingHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) DeleteBucketTaggingHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -3,58 +3,58 @@ package handler
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *handler) SelectObjectContentHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) SelectObjectContentHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetBucketLifecycleHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketLifecycleHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetBucketEncryptionHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketEncryptionHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetBucketWebsiteHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketWebsiteHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetBucketAccelerateHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketAccelerateHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetBucketRequestPaymentHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketRequestPaymentHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetBucketLoggingHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketLoggingHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) GetBucketReplicationHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketReplicationHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) DeleteBucketWebsiteHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) DeleteBucketWebsiteHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) ListenBucketNotificationHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ListenBucketNotificationHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) ListObjectsV2MHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ListObjectsV2MHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) PutBucketLifecycleHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutBucketLifecycleHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) PutBucketEncryptionHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutBucketEncryptionHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
h.logAndSendError(w, "not implemented", middleware.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,21 +11,22 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
s3errors "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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
frosterrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors"
|
frosterrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *handler) reqLogger(ctx context.Context) *zap.Logger {
|
func (h *handler) reqLogger(ctx context.Context) *zap.Logger {
|
||||||
reqLogger := api.GetReqLog(ctx)
|
reqLogger := middleware.GetReqLog(ctx)
|
||||||
if reqLogger != nil {
|
if reqLogger != nil {
|
||||||
return reqLogger
|
return reqLogger
|
||||||
}
|
}
|
||||||
return h.log
|
return h.log
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) logAndSendError(w http.ResponseWriter, logText string, reqInfo *api.ReqInfo, err error, additional ...zap.Field) {
|
func (h *handler) logAndSendError(w http.ResponseWriter, logText string, reqInfo *middleware.ReqInfo, err error, additional ...zap.Field) {
|
||||||
code := api.WriteErrorResponse(w, reqInfo, transformToS3Error(err))
|
code := middleware.WriteErrorResponse(w, reqInfo, transformToS3Error(err))
|
||||||
fields := []zap.Field{
|
fields := []zap.Field{
|
||||||
zap.Int("status", code),
|
zap.Int("status", code),
|
||||||
zap.String("request_id", reqInfo.RequestID),
|
zap.String("request_id", reqInfo.RequestID),
|
||||||
|
@ -38,8 +39,8 @@ func (h *handler) logAndSendError(w http.ResponseWriter, logText string, reqInfo
|
||||||
h.log.Error("request failed", fields...) // consider using h.reqLogger (it requires accept context.Context or http.Request)
|
h.log.Error("request failed", fields...) // consider using h.reqLogger (it requires accept context.Context or http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) logAndSendErrorNoHeader(w http.ResponseWriter, logText string, reqInfo *api.ReqInfo, err error, additional ...zap.Field) {
|
func (h *handler) logAndSendErrorNoHeader(w http.ResponseWriter, logText string, reqInfo *middleware.ReqInfo, err error, additional ...zap.Field) {
|
||||||
api.WriteErrorResponseNoHeader(w, reqInfo, transformToS3Error(err))
|
middleware.WriteErrorResponseNoHeader(w, reqInfo, transformToS3Error(err))
|
||||||
fields := []zap.Field{
|
fields := []zap.Field{
|
||||||
zap.String("request_id", reqInfo.RequestID),
|
zap.String("request_id", reqInfo.RequestID),
|
||||||
zap.String("method", reqInfo.API),
|
zap.String("method", reqInfo.API),
|
||||||
|
|
|
@ -4,14 +4,14 @@ import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"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/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *handler) PutBucketVersioningHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutBucketVersioningHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
configuration := new(VersioningConfiguration)
|
configuration := new(VersioningConfiguration)
|
||||||
if err := xml.NewDecoder(r.Body).Decode(configuration); err != nil {
|
if err := xml.NewDecoder(r.Body).Decode(configuration); err != nil {
|
||||||
|
@ -57,7 +57,7 @@ func (h *handler) PutBucketVersioningHandler(w http.ResponseWriter, r *http.Requ
|
||||||
|
|
||||||
// GetBucketVersioningHandler implements bucket versioning getter handler.
|
// GetBucketVersioningHandler implements bucket versioning getter handler.
|
||||||
func (h *handler) GetBucketVersioningHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketVersioningHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
reqInfo := middleware.GetReqInfo(r.Context())
|
||||||
|
|
||||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -71,7 +71,7 @@ func (h *handler) GetBucketVersioningHandler(w http.ResponseWriter, r *http.Requ
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = api.EncodeToResponse(w, formVersioningConfiguration(settings)); err != nil {
|
if err = middleware.EncodeToResponse(w, formVersioningConfiguration(settings)); err != nil {
|
||||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
objectv2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
objectv2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum"
|
||||||
|
@ -331,7 +331,7 @@ func (t *TestFrostFS) isPublicRead(cnrID cid.ID) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getOwner(ctx context.Context) user.ID {
|
func getOwner(ctx context.Context) user.ID {
|
||||||
if bd, ok := ctx.Value(api.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil && bd.Gate.BearerToken != nil {
|
if bd, ok := ctx.Value(middleware.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil && bd.Gate.BearerToken != nil {
|
||||||
return bearer.ResolveIssuer(*bd.Gate.BearerToken)
|
return bearer.ResolveIssuer(*bd.Gate.BearerToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/encryption"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/encryption"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||||
|
@ -303,13 +304,13 @@ func (n *layer) IsNotificationEnabled() bool {
|
||||||
|
|
||||||
// IsAuthenticatedRequest checks if access box exists in the current request.
|
// IsAuthenticatedRequest checks if access box exists in the current request.
|
||||||
func IsAuthenticatedRequest(ctx context.Context) bool {
|
func IsAuthenticatedRequest(ctx context.Context) bool {
|
||||||
_, ok := ctx.Value(api.BoxData).(*accessbox.Box)
|
_, ok := ctx.Value(middleware.BoxData).(*accessbox.Box)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// TimeNow returns client time from request or time.Now().
|
// TimeNow returns client time from request or time.Now().
|
||||||
func TimeNow(ctx context.Context) time.Time {
|
func TimeNow(ctx context.Context) time.Time {
|
||||||
if now, ok := ctx.Value(api.ClientTime).(time.Time); ok {
|
if now, ok := ctx.Value(middleware.ClientTime).(time.Time); ok {
|
||||||
return now
|
return now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,7 +319,7 @@ func TimeNow(ctx context.Context) time.Time {
|
||||||
|
|
||||||
// Owner returns owner id from BearerToken (context) or from client owner.
|
// Owner returns owner id from BearerToken (context) or from client owner.
|
||||||
func (n *layer) Owner(ctx context.Context) user.ID {
|
func (n *layer) Owner(ctx context.Context) user.ID {
|
||||||
if bd, ok := ctx.Value(api.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil && bd.Gate.BearerToken != nil {
|
if bd, ok := ctx.Value(middleware.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil && bd.Gate.BearerToken != nil {
|
||||||
return bearer.ResolveIssuer(*bd.Gate.BearerToken)
|
return bearer.ResolveIssuer(*bd.Gate.BearerToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,7 +330,7 @@ func (n *layer) Owner(ctx context.Context) user.ID {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) reqLogger(ctx context.Context) *zap.Logger {
|
func (n *layer) reqLogger(ctx context.Context) *zap.Logger {
|
||||||
reqLogger := api.GetReqLog(ctx)
|
reqLogger := middleware.GetReqLog(ctx)
|
||||||
if reqLogger != nil {
|
if reqLogger != nil {
|
||||||
return reqLogger
|
return reqLogger
|
||||||
}
|
}
|
||||||
|
@ -337,7 +338,7 @@ func (n *layer) reqLogger(ctx context.Context) *zap.Logger {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) prepareAuthParameters(ctx context.Context, prm *PrmAuth, bktOwner user.ID) {
|
func (n *layer) prepareAuthParameters(ctx context.Context, prm *PrmAuth, bktOwner user.ID) {
|
||||||
if bd, ok := ctx.Value(api.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil && bd.Gate.BearerToken != nil {
|
if bd, ok := ctx.Value(middleware.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil && bd.Gate.BearerToken != nil {
|
||||||
if bd.Gate.BearerToken.Impersonate() || bktOwner.Equals(bearer.ResolveIssuer(*bd.Gate.BearerToken)) {
|
if bd.Gate.BearerToken.Impersonate() || bktOwner.Equals(bearer.ResolveIssuer(*bd.Gate.BearerToken)) {
|
||||||
prm.BearerToken = bd.Gate.BearerToken
|
prm.BearerToken = bd.Gate.BearerToken
|
||||||
return
|
return
|
||||||
|
|
|
@ -7,13 +7,13 @@ import (
|
||||||
errorsStd "errors"
|
errorsStd "errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PutBucketNotificationConfigurationParams struct {
|
type PutBucketNotificationConfigurationParams struct {
|
||||||
RequestInfo *api.ReqInfo
|
RequestInfo *middleware.ReqInfo
|
||||||
BktInfo *data.BucketInfo
|
BktInfo *data.BucketInfo
|
||||||
Configuration *data.NotificationConfiguration
|
Configuration *data.NotificationConfiguration
|
||||||
CopiesNumbers []uint32
|
CopiesNumbers []uint32
|
||||||
|
|
|
@ -9,9 +9,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/encryption"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/encryption"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
)
|
)
|
||||||
|
@ -141,7 +141,7 @@ func NameFromString(name string) (string, string) {
|
||||||
// GetBoxData extracts accessbox.Box from context.
|
// GetBoxData extracts accessbox.Box from context.
|
||||||
func GetBoxData(ctx context.Context) (*accessbox.Box, error) {
|
func GetBoxData(ctx context.Context) (*accessbox.Box, error) {
|
||||||
var boxData *accessbox.Box
|
var boxData *accessbox.Box
|
||||||
data, ok := ctx.Value(api.BoxData).(*accessbox.Box)
|
data, ok := ctx.Value(middleware.BoxData).(*accessbox.Box)
|
||||||
if !ok || data == nil {
|
if !ok || data == nil {
|
||||||
return nil, fmt.Errorf("couldn't get box data from context")
|
return nil, fmt.Errorf("couldn't get box data from context")
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
bearertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer/test"
|
bearertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer/test"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
|
@ -140,7 +140,7 @@ func prepareContext(t *testing.T, cachesConfig ...*CachesConfig) *testContext {
|
||||||
bearerToken := bearertest.Token()
|
bearerToken := bearertest.Token()
|
||||||
require.NoError(t, bearerToken.Sign(key.PrivateKey))
|
require.NoError(t, bearerToken.Sign(key.PrivateKey))
|
||||||
|
|
||||||
ctx := context.WithValue(context.Background(), api.BoxData, &accessbox.Box{
|
ctx := context.WithValue(context.Background(), middleware.BoxData, &accessbox.Box{
|
||||||
Gate: &accessbox.GateData{
|
Gate: &accessbox.GateData{
|
||||||
BearerToken: &bearerToken,
|
BearerToken: &bearerToken,
|
||||||
GateKey: key.PublicKey(),
|
GateKey: key.PublicKey(),
|
||||||
|
|
282
api/response.go
282
api/response.go
|
@ -1,282 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/version"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
// ErrorResponse -- error response format.
|
|
||||||
ErrorResponse struct {
|
|
||||||
XMLName xml.Name `xml:"Error" json:"-"`
|
|
||||||
Code string
|
|
||||||
Message string
|
|
||||||
Key string `xml:"Key,omitempty" json:"Key,omitempty"`
|
|
||||||
BucketName string `xml:"BucketName,omitempty" json:"BucketName,omitempty"`
|
|
||||||
Resource string
|
|
||||||
RequestID string `xml:"RequestId" json:"RequestId"`
|
|
||||||
HostID string `xml:"HostId" json:"HostId"`
|
|
||||||
|
|
||||||
// The region where the bucket is located. This header is returned
|
|
||||||
// only in HEAD bucket and ListObjects response.
|
|
||||||
Region string `xml:"Region,omitempty" json:"Region,omitempty"`
|
|
||||||
|
|
||||||
// Captures the server string returned in response header.
|
|
||||||
Server string `xml:"-" json:"-"`
|
|
||||||
|
|
||||||
// Underlying HTTP status code for the returned error.
|
|
||||||
StatusCode int `xml:"-" json:"-"`
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
hdrServerInfo = "Server"
|
|
||||||
hdrAcceptRanges = "Accept-Ranges"
|
|
||||||
hdrContentType = "Content-Type"
|
|
||||||
hdrContentLength = "Content-Length"
|
|
||||||
hdrRetryAfter = "Retry-After"
|
|
||||||
|
|
||||||
hdrAmzCopySource = "X-Amz-Copy-Source"
|
|
||||||
|
|
||||||
// Response request id.
|
|
||||||
hdrAmzRequestID = "x-amz-request-id"
|
|
||||||
|
|
||||||
// hdrSSE is the general AWS SSE HTTP header key.
|
|
||||||
hdrSSE = "X-Amz-Server-Side-Encryption"
|
|
||||||
|
|
||||||
// hdrSSECustomerKey is the HTTP header key referencing the
|
|
||||||
// SSE-C client-provided key..
|
|
||||||
hdrSSECustomerKey = hdrSSE + "-Customer-Key"
|
|
||||||
|
|
||||||
// hdrSSECopyKey is the HTTP header key referencing the SSE-C
|
|
||||||
// client-provided key for SSE-C copy requests.
|
|
||||||
hdrSSECopyKey = "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
deploymentID, _ = uuid.NewRandom()
|
|
||||||
|
|
||||||
xmlHeader = []byte(xml.Header)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Non exhaustive list of AWS S3 standard error responses -
|
|
||||||
// http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
|
|
||||||
var s3ErrorResponseMap = map[string]string{
|
|
||||||
"AccessDenied": "Access Denied.",
|
|
||||||
"BadDigest": "The Content-Md5 you specified did not match what we received.",
|
|
||||||
"EntityTooSmall": "Your proposed upload is smaller than the minimum allowed object size.",
|
|
||||||
"EntityTooLarge": "Your proposed upload exceeds the maximum allowed object size.",
|
|
||||||
"IncompleteBody": "You did not provide the number of bytes specified by the Content-Length HTTP header.",
|
|
||||||
"InternalError": "We encountered an internal error, please try again.",
|
|
||||||
"InvalidAccessKeyId": "The access key ID you provided does not exist in our records.",
|
|
||||||
"InvalidBucketName": "The specified bucket is not valid.",
|
|
||||||
"InvalidDigest": "The Content-Md5 you specified is not valid.",
|
|
||||||
"InvalidRange": "The requested range is not satisfiable",
|
|
||||||
"MalformedXML": "The XML you provided was not well-formed or did not validate against our published schema.",
|
|
||||||
"MissingContentLength": "You must provide the Content-Length HTTP header.",
|
|
||||||
"MissingContentMD5": "Missing required header for this request: Content-Md5.",
|
|
||||||
"MissingRequestBodyError": "Request body is empty.",
|
|
||||||
"NoSuchBucket": "The specified bucket does not exist.",
|
|
||||||
"NoSuchBucketPolicy": "The bucket policy does not exist",
|
|
||||||
"NoSuchKey": "The specified key does not exist.",
|
|
||||||
"NoSuchUpload": "The specified multipart upload does not exist. The upload ID may be invalid, or the upload may have been aborted or completed.",
|
|
||||||
"NotImplemented": "A header you provided implies functionality that is not implemented",
|
|
||||||
"PreconditionFailed": "At least one of the pre-conditions you specified did not hold",
|
|
||||||
"RequestTimeTooSkewed": "The difference between the request time and the server's time is too large.",
|
|
||||||
"SignatureDoesNotMatch": "The request signature we calculated does not match the signature you provided. Check your key and signing method.",
|
|
||||||
"MethodNotAllowed": "The specified method is not allowed against this resource.",
|
|
||||||
"InvalidPart": "One or more of the specified parts could not be found.",
|
|
||||||
"InvalidPartOrder": "The list of parts was not in ascending order. The parts list must be specified in order by part number.",
|
|
||||||
"InvalidObjectState": "The operation is not valid for the current state of the object.",
|
|
||||||
"AuthorizationHeaderMalformed": "The authorization header is malformed; the region is wrong.",
|
|
||||||
"MalformedPOSTRequest": "The body of your POST request is not well-formed multipart/form-data.",
|
|
||||||
"BucketNotEmpty": "The bucket you tried to delete is not empty",
|
|
||||||
"AllAccessDisabled": "All access to this bucket has been disabled.",
|
|
||||||
"MalformedPolicy": "Policy has invalid resource.",
|
|
||||||
"MissingFields": "Missing fields in request.",
|
|
||||||
"AuthorizationQueryParametersError": "Error parsing the X-Amz-Credential parameter; the Credential is mal-formed; expecting \"<YOUR-AKID>/YYYYMMDD/REGION/SERVICE/aws4_request\".",
|
|
||||||
"MalformedDate": "Invalid date format header, expected to be in ISO8601, RFC1123 or RFC1123Z time format.",
|
|
||||||
"BucketAlreadyOwnedByYou": "Your previous request to create the named bucket succeeded and you already own it.",
|
|
||||||
"InvalidDuration": "Duration provided in the request is invalid.",
|
|
||||||
"XAmzContentSHA256Mismatch": "The provided 'x-amz-content-sha256' header does not match what was computed.",
|
|
||||||
// Add new API errors here.
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteErrorResponse writes error headers.
|
|
||||||
func WriteErrorResponse(w http.ResponseWriter, reqInfo *ReqInfo, err error) int {
|
|
||||||
code := http.StatusInternalServerError
|
|
||||||
|
|
||||||
if e, ok := err.(errors.Error); ok {
|
|
||||||
code = e.HTTPStatusCode
|
|
||||||
|
|
||||||
switch e.Code {
|
|
||||||
case "SlowDown", "XFrostFSServerNotInitialized", "XFrostFSReadQuorum", "XFrostFSWriteQuorum":
|
|
||||||
// Set retry-after header to indicate user-agents to retry request after 120secs.
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
|
|
||||||
w.Header().Set(hdrRetryAfter, "120")
|
|
||||||
case "AccessDenied":
|
|
||||||
// TODO process when the request is from browser and also if browser
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generates error response.
|
|
||||||
errorResponse := getAPIErrorResponse(reqInfo, err)
|
|
||||||
encodedErrorResponse := EncodeResponse(errorResponse)
|
|
||||||
WriteResponse(w, code, encodedErrorResponse, MimeXML)
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteErrorResponseNoHeader writes XML encoded error to the response body.
|
|
||||||
func WriteErrorResponseNoHeader(w http.ResponseWriter, reqInfo *ReqInfo, err error) {
|
|
||||||
errorResponse := getAPIErrorResponse(reqInfo, err)
|
|
||||||
encodedErrorResponse := EncodeResponse(errorResponse)
|
|
||||||
WriteResponseBody(w, encodedErrorResponse)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If none of the http routes match respond with appropriate errors.
|
|
||||||
func errorResponseHandler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
desc := fmt.Sprintf("Unknown API request at %s", r.URL.Path)
|
|
||||||
WriteErrorResponse(w, GetReqInfo(r.Context()), errors.Error{
|
|
||||||
Code: "UnknownAPIRequest",
|
|
||||||
Description: desc,
|
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write http common headers.
|
|
||||||
func setCommonHeaders(w http.ResponseWriter) {
|
|
||||||
w.Header().Set(hdrServerInfo, version.Server)
|
|
||||||
w.Header().Set(hdrAcceptRanges, "bytes")
|
|
||||||
|
|
||||||
// Remove sensitive information
|
|
||||||
removeSensitiveHeaders(w.Header())
|
|
||||||
}
|
|
||||||
|
|
||||||
// removeSensitiveHeaders removes confidential encryption
|
|
||||||
// information -- e.g. the SSE-C key -- from the HTTP headers.
|
|
||||||
// It has the same semantics as RemoveSensitiveEntries.
|
|
||||||
func removeSensitiveHeaders(h http.Header) {
|
|
||||||
h.Del(hdrSSECustomerKey)
|
|
||||||
h.Del(hdrSSECopyKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteResponse writes given statusCode and response into w (with mType header if set).
|
|
||||||
func WriteResponse(w http.ResponseWriter, statusCode int, response []byte, mType mimeType) {
|
|
||||||
setCommonHeaders(w)
|
|
||||||
if mType != MimeNone {
|
|
||||||
w.Header().Set(hdrContentType, string(mType))
|
|
||||||
}
|
|
||||||
w.Header().Set(hdrContentLength, strconv.Itoa(len(response)))
|
|
||||||
w.WriteHeader(statusCode)
|
|
||||||
if response == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteResponseBody(w, response)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteResponseBody writes response into w.
|
|
||||||
func WriteResponseBody(w http.ResponseWriter, response []byte) {
|
|
||||||
_, _ = w.Write(response)
|
|
||||||
if flusher, ok := w.(http.Flusher); ok {
|
|
||||||
flusher.Flush()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeResponse encodes the response headers into XML format.
|
|
||||||
func EncodeResponse(response interface{}) []byte {
|
|
||||||
var bytesBuffer bytes.Buffer
|
|
||||||
bytesBuffer.WriteString(xml.Header)
|
|
||||||
_ = xml.
|
|
||||||
NewEncoder(&bytesBuffer).
|
|
||||||
Encode(response)
|
|
||||||
return bytesBuffer.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeResponseNoHeader encodes response without setting xml.Header.
|
|
||||||
// Should be used with periodicXMLWriter which sends xml.Header to the client
|
|
||||||
// with whitespaces to keep connection alive.
|
|
||||||
func EncodeResponseNoHeader(response interface{}) []byte {
|
|
||||||
var bytesBuffer bytes.Buffer
|
|
||||||
_ = xml.NewEncoder(&bytesBuffer).Encode(response)
|
|
||||||
return bytesBuffer.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeToResponse encodes the response into ResponseWriter.
|
|
||||||
func EncodeToResponse(w http.ResponseWriter, response interface{}) error {
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
if _, err := w.Write(xmlHeader); err != nil {
|
|
||||||
return fmt.Errorf("write headers: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return EncodeToResponseNoHeader(w, response)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeToResponseNoHeader encodes the response into ResponseWriter without
|
|
||||||
// header status.
|
|
||||||
func EncodeToResponseNoHeader(w http.ResponseWriter, response interface{}) error {
|
|
||||||
if err := xml.NewEncoder(w).Encode(response); err != nil {
|
|
||||||
return fmt.Errorf("encode xml response: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// // WriteSuccessResponseXML writes success headers and response if any,
|
|
||||||
// // with content-type set to `application/xml`.
|
|
||||||
// func WriteSuccessResponseXML(w http.ResponseWriter, response []byte) {
|
|
||||||
// WriteResponse(w, http.StatusOK, response, MimeXML)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// WriteSuccessResponseHeadersOnly writes HTTP (200) OK response with no data
|
|
||||||
// to the client.
|
|
||||||
func WriteSuccessResponseHeadersOnly(w http.ResponseWriter) {
|
|
||||||
WriteResponse(w, http.StatusOK, nil, MimeNone)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error -- Returns S3 error string.
|
|
||||||
func (e ErrorResponse) Error() string {
|
|
||||||
if e.Message == "" {
|
|
||||||
msg, ok := s3ErrorResponseMap[e.Code]
|
|
||||||
if !ok {
|
|
||||||
msg = fmt.Sprintf("Error response code %s.", e.Code)
|
|
||||||
}
|
|
||||||
return msg
|
|
||||||
}
|
|
||||||
return e.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
// getErrorResponse gets in standard error and resource value and
|
|
||||||
// provides an encodable populated response values.
|
|
||||||
func getAPIErrorResponse(info *ReqInfo, err error) ErrorResponse {
|
|
||||||
code := "InternalError"
|
|
||||||
desc := err.Error()
|
|
||||||
|
|
||||||
if e, ok := err.(errors.Error); ok {
|
|
||||||
code = e.Code
|
|
||||||
desc = e.Description
|
|
||||||
}
|
|
||||||
|
|
||||||
var resource string
|
|
||||||
if info.URL != nil {
|
|
||||||
resource = info.URL.Path
|
|
||||||
}
|
|
||||||
|
|
||||||
return ErrorResponse{
|
|
||||||
Code: code,
|
|
||||||
Message: desc,
|
|
||||||
BucketName: info.BucketName,
|
|
||||||
Key: info.ObjectName,
|
|
||||||
Resource: resource,
|
|
||||||
RequestID: info.RequestID,
|
|
||||||
HostID: info.DeploymentID,
|
|
||||||
}
|
|
||||||
}
|
|
795
api/router.go
795
api/router.go
|
@ -2,16 +2,17 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
||||||
|
s3middleware "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/metrics"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/metrics"
|
||||||
"github.com/google/uuid"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/gorilla/mux"
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"google.golang.org/grpc/metadata"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -86,185 +87,64 @@ type (
|
||||||
|
|
||||||
ResolveBucket(ctx context.Context, bucket string) (*data.BucketInfo, error)
|
ResolveBucket(ctx context.Context, bucket string) (*data.BucketInfo, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// mimeType represents various MIME types used in API responses.
|
|
||||||
mimeType string
|
|
||||||
|
|
||||||
logResponseWriter struct {
|
|
||||||
sync.Once
|
|
||||||
http.ResponseWriter
|
|
||||||
|
|
||||||
statusCode int
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
func AttachChi(api *chi.Mux, domains []string, throttle middleware.ThrottleOpts, h Handler, center auth.Center, log *zap.Logger, appMetrics *metrics.AppMetrics) {
|
||||||
// SlashSeparator -- slash separator.
|
api.Use(
|
||||||
SlashSeparator = "/"
|
middleware.CleanPath,
|
||||||
|
s3middleware.Request(log),
|
||||||
|
middleware.ThrottleWithOpts(throttle),
|
||||||
|
middleware.Recoverer,
|
||||||
|
s3middleware.Tracing(),
|
||||||
|
s3middleware.Metrics(log, h.ResolveBucket, appMetrics),
|
||||||
|
s3middleware.LogSuccessResponse(log),
|
||||||
|
s3middleware.Auth(center, log),
|
||||||
|
)
|
||||||
|
|
||||||
// MimeNone means no response type.
|
defaultRouter := chi.NewRouter()
|
||||||
MimeNone mimeType = ""
|
defaultRouter.Mount(fmt.Sprintf("/{%s}", s3middleware.BucketURLPrm), bucketRouter(h, log))
|
||||||
|
defaultRouter.Get("/", named("ListBuckets", h.ListBucketsHandler))
|
||||||
|
|
||||||
// MimeXML means response type is XML.
|
hr := NewHostBucketRouter("bucket")
|
||||||
MimeXML mimeType = "application/xml"
|
hr.Default(defaultRouter)
|
||||||
)
|
for _, domain := range domains {
|
||||||
|
hr.Map(domain, bucketRouter(h, log))
|
||||||
|
}
|
||||||
|
api.Mount("/", hr)
|
||||||
|
|
||||||
var _ = logSuccessResponse
|
attachErrorHandler(api, h, center, log, appMetrics)
|
||||||
|
|
||||||
func (lrw *logResponseWriter) WriteHeader(code int) {
|
|
||||||
lrw.Do(func() {
|
|
||||||
lrw.statusCode = code
|
|
||||||
lrw.ResponseWriter.WriteHeader(code)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lrw *logResponseWriter) Flush() {
|
func named(name string, handlerFunc http.HandlerFunc) http.HandlerFunc {
|
||||||
if f, ok := lrw.ResponseWriter.(http.Flusher); ok {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
f.Flush()
|
reqInfo := s3middleware.GetReqInfo(r.Context())
|
||||||
|
reqInfo.API = name
|
||||||
|
handlerFunc.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareRequest(log *zap.Logger) mux.MiddlewareFunc {
|
func setErrorAPI(apiName string, h http.Handler) http.HandlerFunc {
|
||||||
return func(h http.Handler) http.Handler {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ctx := s3middleware.SetReqInfo(r.Context(), &s3middleware.ReqInfo{API: apiName})
|
||||||
// generate random UUIDv4
|
|
||||||
id, _ := uuid.NewRandom()
|
|
||||||
|
|
||||||
// set request id into response header
|
|
||||||
// also we have to set request id here
|
|
||||||
// to be able to get it in prepareReqInfo
|
|
||||||
w.Header().Set(hdrAmzRequestID, id.String())
|
|
||||||
|
|
||||||
// set request info into context
|
|
||||||
reqInfo := prepareReqInfo(w, r)
|
|
||||||
r = r.WithContext(SetReqInfo(r.Context(), reqInfo))
|
|
||||||
|
|
||||||
// set request id into gRPC meta header
|
|
||||||
r = r.WithContext(metadata.AppendToOutgoingContext(
|
|
||||||
r.Context(), hdrAmzRequestID, reqInfo.RequestID,
|
|
||||||
))
|
|
||||||
|
|
||||||
// set request scoped child logger into context
|
|
||||||
additionalFields := []zap.Field{zap.String("request_id", reqInfo.RequestID),
|
|
||||||
zap.String("method", reqInfo.API), zap.String("bucket", reqInfo.BucketName)}
|
|
||||||
|
|
||||||
if isObjectRequest(reqInfo) {
|
|
||||||
additionalFields = append(additionalFields, zap.String("object", reqInfo.ObjectName))
|
|
||||||
}
|
|
||||||
reqLogger := log.With(additionalFields...)
|
|
||||||
|
|
||||||
r = r.WithContext(SetReqLogger(r.Context(), reqLogger))
|
|
||||||
|
|
||||||
reqLogger.Info("request start", zap.String("host", r.Host),
|
|
||||||
zap.String("remote_host", reqInfo.RemoteHost))
|
|
||||||
|
|
||||||
// continue execution
|
|
||||||
h.ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var objectMethods = []string{
|
|
||||||
"HeadObject", "GetObject", "DeleteObject", "PutObject", "PostObject", "CopyObject",
|
|
||||||
"CreateMultipartUpload", "UploadPartCopy", "UploadPart", "ListObjectParts",
|
|
||||||
"CompleteMultipartUpload", "AbortMultipartUpload",
|
|
||||||
"PutObjectACL", "GetObjectACL",
|
|
||||||
"PutObjectTagging", "GetObjectTagging", "DeleteObjectTagging",
|
|
||||||
"PutObjectRetention", "GetObjectRetention", "PutObjectLegalHold", "getobjectlegalhold",
|
|
||||||
"SelectObjectContent", "GetObjectAttributes",
|
|
||||||
}
|
|
||||||
|
|
||||||
func isObjectRequest(info *ReqInfo) bool {
|
|
||||||
for _, method := range objectMethods {
|
|
||||||
if info.API == method {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func appendCORS(handler Handler) mux.MiddlewareFunc {
|
|
||||||
return func(h http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
handler.AppendCORSHeaders(w, r)
|
|
||||||
h.ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketResolveFunc is a func to resolve bucket info by name.
|
|
||||||
type BucketResolveFunc func(ctx context.Context, bucket string) (*data.BucketInfo, error)
|
|
||||||
|
|
||||||
// metricsMiddleware wraps http handler for api with basic statistics collection.
|
|
||||||
func metricsMiddleware(log *zap.Logger, resolveBucket BucketResolveFunc, appMetrics *metrics.AppMetrics) mux.MiddlewareFunc {
|
|
||||||
return func(h http.Handler) http.Handler {
|
|
||||||
return Stats(h.ServeHTTP, resolveCID(log, resolveBucket), appMetrics)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolveCID forms CIDResolveFunc using BucketResolveFunc.
|
|
||||||
func resolveCID(log *zap.Logger, resolveBucket BucketResolveFunc) CIDResolveFunc {
|
|
||||||
return func(ctx context.Context, reqInfo *ReqInfo) (cnrID string) {
|
|
||||||
if reqInfo.BucketName == "" || reqInfo.API == "CreateBucket" || reqInfo.API == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
bktInfo, err := resolveBucket(ctx, reqInfo.BucketName)
|
|
||||||
if err != nil {
|
|
||||||
reqLogOrDefault(ctx, log).Debug("failed to resolve CID", zap.Error(err))
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return bktInfo.CID.EncodeToString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func logSuccessResponse(l *zap.Logger) mux.MiddlewareFunc {
|
|
||||||
return func(h http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
lw := &logResponseWriter{ResponseWriter: w}
|
|
||||||
|
|
||||||
reqLogger := reqLogOrDefault(r.Context(), l)
|
|
||||||
|
|
||||||
// pass execution:
|
|
||||||
h.ServeHTTP(lw, r)
|
|
||||||
|
|
||||||
// Ignore >400 status codes
|
|
||||||
if lw.statusCode >= http.StatusBadRequest {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
reqLogger.Info("request end",
|
|
||||||
zap.Int("status", lw.statusCode),
|
|
||||||
zap.String("description", http.StatusText(lw.statusCode)))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRequestID returns the request ID from the response writer or the context.
|
|
||||||
func GetRequestID(v interface{}) string {
|
|
||||||
switch t := v.(type) {
|
|
||||||
case context.Context:
|
|
||||||
return GetReqInfo(t).RequestID
|
|
||||||
case http.ResponseWriter:
|
|
||||||
return t.Header().Get(hdrAmzRequestID)
|
|
||||||
default:
|
|
||||||
panic("unknown type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setErrorAPI(apiName string, h http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ctx := SetReqInfo(r.Context(), &ReqInfo{API: apiName})
|
|
||||||
h.ServeHTTP(w, r.WithContext(ctx))
|
h.ServeHTTP(w, r.WithContext(ctx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If none of the http routes match respond with appropriate errors.
|
||||||
|
func errorResponseHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
desc := fmt.Sprintf("Unknown API request at %s", r.URL.Path)
|
||||||
|
s3middleware.WriteErrorResponse(w, s3middleware.GetReqInfo(r.Context()), errors.Error{
|
||||||
|
Code: "UnknownAPIRequest",
|
||||||
|
Description: desc,
|
||||||
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// attachErrorHandler set NotFoundHandler and MethodNotAllowedHandler for mux.Router.
|
// attachErrorHandler set NotFoundHandler and MethodNotAllowedHandler for chi.Router.
|
||||||
func attachErrorHandler(api *mux.Router, log *zap.Logger, h Handler, center auth.Center, appMetrics *metrics.AppMetrics) {
|
func attachErrorHandler(api *chi.Mux, h Handler, center auth.Center, log *zap.Logger, appMetrics *metrics.AppMetrics) {
|
||||||
middlewares := []mux.MiddlewareFunc{
|
middlewares := chi.Middlewares{
|
||||||
AuthMiddleware(log, center),
|
s3middleware.Auth(center, log),
|
||||||
metricsMiddleware(log, h.ResolveBucket, appMetrics),
|
s3middleware.Metrics(log, h.ResolveBucket, appMetrics),
|
||||||
}
|
}
|
||||||
|
|
||||||
var errorHandler http.Handler = http.HandlerFunc(errorResponseHandler)
|
var errorHandler http.Handler = http.HandlerFunc(errorResponseHandler)
|
||||||
|
@ -273,367 +153,240 @@ func attachErrorHandler(api *mux.Router, log *zap.Logger, h Handler, center auth
|
||||||
}
|
}
|
||||||
|
|
||||||
// If none of the routes match, add default error handler routes
|
// If none of the routes match, add default error handler routes
|
||||||
api.NotFoundHandler = setErrorAPI("NotFound", errorHandler)
|
api.NotFound(setErrorAPI("NotFound", errorHandler))
|
||||||
api.MethodNotAllowedHandler = setErrorAPI("MethodNotAllowed", errorHandler)
|
api.MethodNotAllowed(setErrorAPI("MethodNotAllowed", errorHandler))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach adds S3 API handlers from h to r for domains with m client limit using
|
func bucketRouter(h Handler, log *zap.Logger) chi.Router {
|
||||||
// center authentication and log logger.
|
bktRouter := chi.NewRouter()
|
||||||
func Attach(r *mux.Router, domains []string, m MaxClients, h Handler, center auth.Center, log *zap.Logger, appMetrics *metrics.AppMetrics) {
|
bktRouter.Use(
|
||||||
api := r.PathPrefix(SlashSeparator).Subrouter()
|
s3middleware.AddBucketName(log),
|
||||||
|
s3middleware.WrapHandler(h.AppendCORSHeaders),
|
||||||
api.Use(
|
|
||||||
// -- prepare request
|
|
||||||
prepareRequest(log),
|
|
||||||
|
|
||||||
// Attach user authentication for all S3 routes.
|
|
||||||
AuthMiddleware(log, center),
|
|
||||||
|
|
||||||
TracingMiddleware(),
|
|
||||||
|
|
||||||
metricsMiddleware(log, h.ResolveBucket, appMetrics),
|
|
||||||
|
|
||||||
// -- logging error requests
|
|
||||||
logSuccessResponse(log),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
attachErrorHandler(api, log, h, center, appMetrics)
|
bktRouter.Mount(fmt.Sprintf("/{%s}", s3middleware.ObjectURLPrm), objectRouter(h, log))
|
||||||
|
|
||||||
buckets := make([]*mux.Router, 0, len(domains)+1)
|
bktRouter.Options("/", h.Preflight)
|
||||||
buckets = append(buckets, api.PathPrefix("/{bucket}").Subrouter())
|
|
||||||
|
|
||||||
for _, domain := range domains {
|
bktRouter.Head("/", named("HeadBucket", h.HeadBucketHandler))
|
||||||
buckets = append(buckets, api.Host("{bucket:.+}."+domain).Subrouter())
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, bucket := range buckets {
|
// GET method handlers
|
||||||
// Object operations
|
bktRouter.Group(func(r chi.Router) {
|
||||||
// HeadObject
|
r.Method(http.MethodGet, "/", NewHandlerFilter().
|
||||||
bucket.Use(
|
Add(NewFilter().
|
||||||
// -- append CORS headers to a response for
|
Queries("upload").
|
||||||
appendCORS(h),
|
Handler(named("ListMultipartUploads", h.ListMultipartUploadsHandler))).
|
||||||
)
|
Add(NewFilter().
|
||||||
bucket.Methods(http.MethodOptions).HandlerFunc(
|
Queries("location").
|
||||||
m.Handle(h.Preflight)).
|
Handler(named("GetBucketLocation", h.GetBucketLocationHandler))).
|
||||||
Name("Options")
|
Add(NewFilter().
|
||||||
bucket.Methods(http.MethodHead).Path("/{object:.+}").HandlerFunc(
|
Queries("policy").
|
||||||
m.Handle(h.HeadObjectHandler)).
|
Handler(named("GetBucketPolicy", h.GetBucketPolicyHandler))).
|
||||||
Name("HeadObject")
|
Add(NewFilter().
|
||||||
// CopyObjectPart
|
Queries("lifecycle").
|
||||||
bucket.Methods(http.MethodPut).Path("/{object:.+}").Headers(hdrAmzCopySource, "").HandlerFunc(
|
Handler(named("GetBucketLifecycle", h.GetBucketLifecycleHandler))).
|
||||||
m.Handle(h.UploadPartCopy)).
|
Add(NewFilter().
|
||||||
Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}").
|
Queries("encryption").
|
||||||
Name("UploadPartCopy")
|
Handler(named("GetBucketEncryption", h.GetBucketEncryptionHandler))).
|
||||||
// PutObjectPart
|
Add(NewFilter().
|
||||||
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
|
Queries("cors").
|
||||||
m.Handle(h.UploadPartHandler)).
|
Handler(named("GetBucketCors", h.GetBucketCorsHandler))).
|
||||||
Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}").
|
Add(NewFilter().
|
||||||
Name("UploadPart")
|
Queries("acl").
|
||||||
// ListParts
|
Handler(named("GetBucketACL", h.GetBucketACLHandler))).
|
||||||
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
Add(NewFilter().
|
||||||
m.Handle(h.ListPartsHandler)).
|
Queries("website").
|
||||||
Queries("uploadId", "{uploadId:.*}").
|
Handler(named("GetBucketWebsite", h.GetBucketWebsiteHandler))).
|
||||||
Name("ListObjectParts")
|
Add(NewFilter().
|
||||||
// CompleteMultipartUpload
|
Queries("accelerate").
|
||||||
bucket.Methods(http.MethodPost).Path("/{object:.+}").HandlerFunc(
|
Handler(named("GetBucketAccelerate", h.GetBucketAccelerateHandler))).
|
||||||
m.Handle(h.CompleteMultipartUploadHandler)).
|
Add(NewFilter().
|
||||||
Queries("uploadId", "{uploadId:.*}").
|
Queries("requestPayment").
|
||||||
Name("CompleteMultipartUpload")
|
Handler(named("GetBucketRequestPayment", h.GetBucketRequestPaymentHandler))).
|
||||||
// CreateMultipartUpload
|
Add(NewFilter().
|
||||||
bucket.Methods(http.MethodPost).Path("/{object:.+}").HandlerFunc(
|
Queries("logging").
|
||||||
m.Handle(h.CreateMultipartUploadHandler)).
|
Handler(named("GetBucketLogging", h.GetBucketLoggingHandler))).
|
||||||
Queries("uploads", "").
|
Add(NewFilter().
|
||||||
Name("CreateMultipartUpload")
|
Queries("replication").
|
||||||
// AbortMultipartUpload
|
Handler(named("GetBucketReplication", h.GetBucketReplicationHandler))).
|
||||||
bucket.Methods(http.MethodDelete).Path("/{object:.+}").HandlerFunc(
|
Add(NewFilter().
|
||||||
m.Handle(h.AbortMultipartUploadHandler)).
|
Queries("tagging").
|
||||||
Queries("uploadId", "{uploadId:.*}").
|
Handler(named("GetBucketTagging", h.GetBucketTaggingHandler))).
|
||||||
Name("AbortMultipartUpload")
|
Add(NewFilter().
|
||||||
// ListMultipartUploads
|
Queries("object-lock").
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
Handler(named("GetBucketObjectLockConfig", h.GetBucketObjectLockConfigHandler))).
|
||||||
m.Handle(h.ListMultipartUploadsHandler)).
|
Add(NewFilter().
|
||||||
Queries("uploads", "").
|
Queries("versioning").
|
||||||
Name("ListMultipartUploads")
|
Handler(named("GetBucketVersioning", h.GetBucketVersioningHandler))).
|
||||||
// GetObjectACL -- this is a dummy call.
|
Add(NewFilter().
|
||||||
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
Queries("notification").
|
||||||
m.Handle(h.GetObjectACLHandler)).
|
Handler(named("GetBucketNotification", h.GetBucketNotificationHandler))).
|
||||||
Queries("acl", "").
|
Add(NewFilter().
|
||||||
Name("GetObjectACL")
|
Queries("events").
|
||||||
// PutObjectACL -- this is a dummy call.
|
Handler(named("ListenBucketNotification", h.ListenBucketNotificationHandler))).
|
||||||
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
|
Add(NewFilter().
|
||||||
m.Handle(h.PutObjectACLHandler)).
|
QueriesMatch("list-type", "2", "metadata", "true").
|
||||||
Queries("acl", "").
|
Handler(named("ListObjectsV2M", h.ListObjectsV2MHandler))).
|
||||||
Name("PutObjectACL")
|
Add(NewFilter().
|
||||||
// GetObjectTagging
|
QueriesMatch("list-type", "2").
|
||||||
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
Handler(named("ListObjectsV2", h.ListObjectsV2Handler))).
|
||||||
m.Handle(h.GetObjectTaggingHandler)).
|
Add(NewFilter().
|
||||||
Queries("tagging", "").
|
Queries("versions").
|
||||||
Name("GetObjectTagging")
|
Handler(named("ListBucketObjectVersions", h.ListBucketObjectVersionsHandler))).
|
||||||
// PutObjectTagging
|
DefaultHandler(named("ListObjectsV1", h.ListObjectsV1Handler)))
|
||||||
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
|
})
|
||||||
m.Handle(h.PutObjectTaggingHandler)).
|
|
||||||
Queries("tagging", "").
|
|
||||||
Name("PutObjectTagging")
|
|
||||||
// DeleteObjectTagging
|
|
||||||
bucket.Methods(http.MethodDelete).Path("/{object:.+}").HandlerFunc(
|
|
||||||
m.Handle(h.DeleteObjectTaggingHandler)).
|
|
||||||
Queries("tagging", "").
|
|
||||||
Name("DeleteObjectTagging")
|
|
||||||
// SelectObjectContent
|
|
||||||
bucket.Methods(http.MethodPost).Path("/{object:.+}").HandlerFunc(
|
|
||||||
m.Handle(h.SelectObjectContentHandler)).
|
|
||||||
Queries("select", "").Queries("select-type", "2").
|
|
||||||
Name("SelectObjectContent")
|
|
||||||
// GetObjectRetention
|
|
||||||
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
|
||||||
m.Handle(h.GetObjectRetentionHandler)).
|
|
||||||
Queries("retention", "").
|
|
||||||
Name("GetObjectRetention")
|
|
||||||
// GetObjectLegalHold
|
|
||||||
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
|
||||||
m.Handle(h.GetObjectLegalHoldHandler)).
|
|
||||||
Queries("legal-hold", "").
|
|
||||||
Name("GetObjectLegalHold")
|
|
||||||
// GetObjectAttributes
|
|
||||||
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
|
||||||
m.Handle(h.GetObjectAttributesHandler)).
|
|
||||||
Queries("attributes", "").
|
|
||||||
Name("GetObjectAttributes")
|
|
||||||
// GetObject
|
|
||||||
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
|
||||||
m.Handle(h.GetObjectHandler)).
|
|
||||||
Name("GetObject")
|
|
||||||
// CopyObject
|
|
||||||
bucket.Methods(http.MethodPut).Path("/{object:.+}").Headers(hdrAmzCopySource, "").HandlerFunc(
|
|
||||||
m.Handle(h.CopyObjectHandler)).
|
|
||||||
Name("CopyObject")
|
|
||||||
// PutObjectRetention
|
|
||||||
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
|
|
||||||
m.Handle(h.PutObjectRetentionHandler)).
|
|
||||||
Queries("retention", "").
|
|
||||||
Name("PutObjectRetention")
|
|
||||||
// PutObjectLegalHold
|
|
||||||
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
|
|
||||||
m.Handle(h.PutObjectLegalHoldHandler)).
|
|
||||||
Queries("legal-hold", "").
|
|
||||||
Name("PutObjectLegalHold")
|
|
||||||
|
|
||||||
// PutObject
|
// PUT method handlers
|
||||||
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
|
bktRouter.Group(func(r chi.Router) {
|
||||||
m.Handle(h.PutObjectHandler)).
|
r.Method(http.MethodPut, "/", NewHandlerFilter().
|
||||||
Name("PutObject")
|
Add(NewFilter().
|
||||||
// DeleteObject
|
Queries("cors").
|
||||||
bucket.Methods(http.MethodDelete).Path("/{object:.+}").HandlerFunc(
|
Handler(named("PutBucketCors", h.PutBucketCorsHandler))).
|
||||||
m.Handle(h.DeleteObjectHandler)).
|
Add(NewFilter().
|
||||||
Name("DeleteObject")
|
Queries("acl").
|
||||||
|
Handler(named("PutBucketACL", h.PutBucketACLHandler))).
|
||||||
|
Add(NewFilter().
|
||||||
|
Queries("lifecycle").
|
||||||
|
Handler(named("PutBucketLifecycle", h.PutBucketLifecycleHandler))).
|
||||||
|
Add(NewFilter().
|
||||||
|
Queries("encryption").
|
||||||
|
Handler(named("PutBucketEncryption", h.PutBucketEncryptionHandler))).
|
||||||
|
Add(NewFilter().
|
||||||
|
Queries("policy").
|
||||||
|
Handler(named("PutBucketPolicy", h.PutBucketPolicyHandler))).
|
||||||
|
Add(NewFilter().
|
||||||
|
Queries("object-lock").
|
||||||
|
Handler(named("PutBucketObjectLockConfig", h.PutBucketObjectLockConfigHandler))).
|
||||||
|
Add(NewFilter().
|
||||||
|
Queries("tagging").
|
||||||
|
Handler(named("PutBucketTagging", h.PutBucketTaggingHandler))).
|
||||||
|
Add(NewFilter().
|
||||||
|
Queries("versioning").
|
||||||
|
Handler(named("PutBucketVersioning", h.PutBucketVersioningHandler))).
|
||||||
|
Add(NewFilter().
|
||||||
|
Queries("notification").
|
||||||
|
Handler(named("PutBucketNotification", h.PutBucketNotificationHandler))).
|
||||||
|
DefaultHandler(named("CreateBucket", h.CreateBucketHandler)))
|
||||||
|
})
|
||||||
|
|
||||||
// Bucket operations
|
// POST method handlers
|
||||||
// GetBucketLocation
|
bktRouter.Group(func(r chi.Router) {
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
r.Method(http.MethodPost, "/", NewHandlerFilter().
|
||||||
m.Handle(h.GetBucketLocationHandler)).
|
Add(NewFilter().
|
||||||
Queries("location", "").
|
Queries("delete").
|
||||||
Name("GetBucketLocation")
|
Handler(named("DeleteMultipleObjects", h.DeleteMultipleObjectsHandler))).
|
||||||
// GetBucketPolicy
|
// todo consider add filter to match header for defaultHandler: hdrContentType, "multipart/form-data*"
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
DefaultHandler(named("PostObject", h.PostObject)))
|
||||||
m.Handle(h.GetBucketPolicyHandler)).
|
})
|
||||||
Queries("policy", "").
|
|
||||||
Name("GetBucketPolicy")
|
|
||||||
// GetBucketLifecycle
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.GetBucketLifecycleHandler)).
|
|
||||||
Queries("lifecycle", "").
|
|
||||||
Name("GetBucketLifecycle")
|
|
||||||
// GetBucketEncryption
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.GetBucketEncryptionHandler)).
|
|
||||||
Queries("encryption", "").
|
|
||||||
Name("GetBucketEncryption")
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.GetBucketCorsHandler)).
|
|
||||||
Queries("cors", "").
|
|
||||||
Name("GetBucketCors")
|
|
||||||
bucket.Methods(http.MethodPut).HandlerFunc(
|
|
||||||
m.Handle(h.PutBucketCorsHandler)).
|
|
||||||
Queries("cors", "").
|
|
||||||
Name("PutBucketCors")
|
|
||||||
bucket.Methods(http.MethodDelete).HandlerFunc(
|
|
||||||
m.Handle(h.DeleteBucketCorsHandler)).
|
|
||||||
Queries("cors", "").
|
|
||||||
Name("DeleteBucketCors")
|
|
||||||
// Dummy Bucket Calls
|
|
||||||
// GetBucketACL -- this is a dummy call.
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.GetBucketACLHandler)).
|
|
||||||
Queries("acl", "").
|
|
||||||
Name("GetBucketACL")
|
|
||||||
// PutBucketACL -- this is a dummy call.
|
|
||||||
bucket.Methods(http.MethodPut).HandlerFunc(
|
|
||||||
m.Handle(h.PutBucketACLHandler)).
|
|
||||||
Queries("acl", "").
|
|
||||||
Name("PutBucketACL")
|
|
||||||
// GetBucketWebsiteHandler -- this is a dummy call.
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.GetBucketWebsiteHandler)).
|
|
||||||
Queries("website", "").
|
|
||||||
Name("GetBucketWebsite")
|
|
||||||
// GetBucketAccelerateHandler -- this is a dummy call.
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.GetBucketAccelerateHandler)).
|
|
||||||
Queries("accelerate", "").
|
|
||||||
Name("GetBucketAccelerate")
|
|
||||||
// GetBucketRequestPaymentHandler -- this is a dummy call.
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.GetBucketRequestPaymentHandler)).
|
|
||||||
Queries("requestPayment", "").
|
|
||||||
Name("GetBucketRequestPayment")
|
|
||||||
// GetBucketLoggingHandler -- this is a dummy call.
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.GetBucketLoggingHandler)).
|
|
||||||
Queries("logging", "").
|
|
||||||
Name("GetBucketLogging")
|
|
||||||
// GetBucketReplicationHandler -- this is a dummy call.
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.GetBucketReplicationHandler)).
|
|
||||||
Queries("replication", "").
|
|
||||||
Name("GetBucketReplication")
|
|
||||||
// GetBucketTaggingHandler
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.GetBucketTaggingHandler)).
|
|
||||||
Queries("tagging", "").
|
|
||||||
Name("GetBucketTagging")
|
|
||||||
// DeleteBucketWebsiteHandler
|
|
||||||
bucket.Methods(http.MethodDelete).HandlerFunc(
|
|
||||||
m.Handle(h.DeleteBucketWebsiteHandler)).
|
|
||||||
Queries("website", "").
|
|
||||||
Name("DeleteBucketWebsite")
|
|
||||||
// DeleteBucketTaggingHandler
|
|
||||||
bucket.Methods(http.MethodDelete).HandlerFunc(
|
|
||||||
m.Handle(h.DeleteBucketTaggingHandler)).
|
|
||||||
Queries("tagging", "").
|
|
||||||
Name("DeleteBucketTagging")
|
|
||||||
|
|
||||||
// GetBucketObjectLockConfig
|
// DELETE method handlers
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
bktRouter.Group(func(r chi.Router) {
|
||||||
m.Handle(h.GetBucketObjectLockConfigHandler)).
|
r.Method(http.MethodDelete, "/", NewHandlerFilter().
|
||||||
Queries("object-lock", "").
|
Add(NewFilter().
|
||||||
Name("GetBucketObjectLockConfig")
|
Queries("cors").
|
||||||
// GetBucketVersioning
|
Handler(named("DeleteBucketCors", h.DeleteBucketCorsHandler))).
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
Add(NewFilter().
|
||||||
m.Handle(h.GetBucketVersioningHandler)).
|
Queries("website").
|
||||||
Queries("versioning", "").
|
Handler(named("DeleteBucketWebsite", h.DeleteBucketWebsiteHandler))).
|
||||||
Name("GetBucketVersioning")
|
Add(NewFilter().
|
||||||
// GetBucketNotification
|
Queries("tagging").
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
Handler(named("DeleteBucketTagging", h.DeleteBucketTaggingHandler))).
|
||||||
m.Handle(h.GetBucketNotificationHandler)).
|
Add(NewFilter().
|
||||||
Queries("notification", "").
|
Queries("policy").
|
||||||
Name("GetBucketNotification")
|
Handler(named("PutBucketPolicy", h.PutBucketPolicyHandler))).
|
||||||
// ListenBucketNotification
|
Add(NewFilter().
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(h.ListenBucketNotificationHandler).
|
Queries("lifecycle").
|
||||||
Queries("events", "{events:.*}").
|
Handler(named("PutBucketLifecycle", h.PutBucketLifecycleHandler))).
|
||||||
Name("ListenBucketNotification")
|
Add(NewFilter().
|
||||||
// ListObjectsV2M
|
Queries("encryption").
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
Handler(named("DeleteBucketEncryption", h.DeleteBucketEncryptionHandler))).
|
||||||
m.Handle(h.ListObjectsV2MHandler)).
|
DefaultHandler(named("DeleteBucket", h.DeleteBucketHandler)))
|
||||||
Queries("list-type", "2", "metadata", "true").
|
})
|
||||||
Name("ListObjectsV2M")
|
|
||||||
// ListObjectsV2
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.ListObjectsV2Handler)).
|
|
||||||
Queries("list-type", "2").
|
|
||||||
Name("ListObjectsV2")
|
|
||||||
// ListBucketVersions
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.ListBucketObjectVersionsHandler)).
|
|
||||||
Queries("versions", "").
|
|
||||||
Name("ListBucketVersions")
|
|
||||||
// ListObjectsV1 (Legacy)
|
|
||||||
bucket.Methods(http.MethodGet).HandlerFunc(
|
|
||||||
m.Handle(h.ListObjectsV1Handler)).
|
|
||||||
Name("ListObjectsV1")
|
|
||||||
// PutBucketLifecycle
|
|
||||||
bucket.Methods(http.MethodPut).HandlerFunc(
|
|
||||||
m.Handle(h.PutBucketLifecycleHandler)).
|
|
||||||
Queries("lifecycle", "").
|
|
||||||
Name("PutBucketLifecycle")
|
|
||||||
// PutBucketEncryption
|
|
||||||
bucket.Methods(http.MethodPut).HandlerFunc(
|
|
||||||
m.Handle(h.PutBucketEncryptionHandler)).
|
|
||||||
Queries("encryption", "").
|
|
||||||
Name("PutBucketEncryption")
|
|
||||||
|
|
||||||
// PutBucketPolicy
|
return bktRouter
|
||||||
bucket.Methods(http.MethodPut).HandlerFunc(
|
}
|
||||||
m.Handle(h.PutBucketPolicyHandler)).
|
|
||||||
Queries("policy", "").
|
func objectRouter(h Handler, l *zap.Logger) chi.Router {
|
||||||
Name("PutBucketPolicy")
|
objRouter := chi.NewRouter()
|
||||||
|
objRouter.Use(s3middleware.AddObjectName(l))
|
||||||
// PutBucketObjectLockConfig
|
|
||||||
bucket.Methods(http.MethodPut).HandlerFunc(
|
objRouter.Head("/", named("HeadObject", h.HeadObjectHandler))
|
||||||
m.Handle(h.PutBucketObjectLockConfigHandler)).
|
|
||||||
Queries("object-lock", "").
|
// GET method handlers
|
||||||
Name("PutBucketObjectLockConfig")
|
objRouter.Group(func(r chi.Router) {
|
||||||
// PutBucketTaggingHandler
|
r.Method(http.MethodGet, "/", NewHandlerFilter().
|
||||||
bucket.Methods(http.MethodPut).HandlerFunc(
|
Add(NewFilter().
|
||||||
m.Handle(h.PutBucketTaggingHandler)).
|
Queries("uploadId").
|
||||||
Queries("tagging", "").
|
Handler(named("ListParts", h.ListPartsHandler))).
|
||||||
Name("PutBucketTagging")
|
Add(NewFilter().
|
||||||
// PutBucketVersioning
|
Queries("acl").
|
||||||
bucket.Methods(http.MethodPut).HandlerFunc(
|
Handler(named("GetObjectACL", h.GetObjectACLHandler))).
|
||||||
m.Handle(h.PutBucketVersioningHandler)).
|
Add(NewFilter().
|
||||||
Queries("versioning", "").
|
Queries("tagging").
|
||||||
Name("PutBucketVersioning")
|
Handler(named("GetObjectTagging", h.GetObjectTaggingHandler))).
|
||||||
// PutBucketNotification
|
Add(NewFilter().
|
||||||
bucket.Methods(http.MethodPut).HandlerFunc(
|
Queries("retention").
|
||||||
m.Handle(h.PutBucketNotificationHandler)).
|
Handler(named("GetObjectRetention", h.GetObjectRetentionHandler))).
|
||||||
Queries("notification", "").
|
Add(NewFilter().
|
||||||
Name("PutBucketNotification")
|
Queries("legal-hold").
|
||||||
// CreateBucket
|
Handler(named("GetObjectLegalHold", h.GetObjectLegalHoldHandler))).
|
||||||
bucket.Methods(http.MethodPut).HandlerFunc(
|
Add(NewFilter().
|
||||||
m.Handle(h.CreateBucketHandler)).
|
Queries("attributes").
|
||||||
Name("CreateBucket")
|
Handler(named("GetObjectAttributes", h.GetObjectAttributesHandler))).
|
||||||
// HeadBucket
|
DefaultHandler(named("GetObject", h.GetObjectHandler)))
|
||||||
bucket.Methods(http.MethodHead).HandlerFunc(
|
})
|
||||||
m.Handle(h.HeadBucketHandler)).
|
|
||||||
Name("HeadBucket")
|
// PUT method handlers
|
||||||
// PostPolicy
|
objRouter.Group(func(r chi.Router) {
|
||||||
bucket.Methods(http.MethodPost).HeadersRegexp(hdrContentType, "multipart/form-data*").HandlerFunc(
|
r.Method(http.MethodPut, "/", NewHandlerFilter().
|
||||||
m.Handle(h.PostObject)).
|
Add(NewFilter().
|
||||||
Name("PostObject")
|
Headers(AmzCopySource).
|
||||||
// DeleteMultipleObjects
|
Queries("partNumber", "uploadId").
|
||||||
bucket.Methods(http.MethodPost).HandlerFunc(
|
Handler(named("UploadPartCopy", h.UploadPartCopy))).
|
||||||
m.Handle(h.DeleteMultipleObjectsHandler)).
|
Add(NewFilter().
|
||||||
Queries("delete", "").
|
Queries("partNumber", "uploadId").
|
||||||
Name("DeleteMultipleObjects")
|
Handler(named("UploadPart", h.UploadPartHandler))).
|
||||||
// DeleteBucketPolicy
|
Add(NewFilter().
|
||||||
bucket.Methods(http.MethodDelete).HandlerFunc(
|
Queries("acl").
|
||||||
m.Handle(h.DeleteBucketPolicyHandler)).
|
Handler(named("PutObjectACL", h.PutObjectACLHandler))).
|
||||||
Queries("policy", "").
|
Add(NewFilter().
|
||||||
Name("DeleteBucketPolicy")
|
Queries("tagging").
|
||||||
// DeleteBucketLifecycle
|
Handler(named("PutObjectTagging", h.PutObjectTaggingHandler))).
|
||||||
bucket.Methods(http.MethodDelete).HandlerFunc(
|
Add(NewFilter().
|
||||||
m.Handle(h.DeleteBucketLifecycleHandler)).
|
Headers(AmzCopySource).
|
||||||
Queries("lifecycle", "").
|
Handler(named("CopyObject", h.CopyObjectHandler))).
|
||||||
Name("DeleteBucketLifecycle")
|
Add(NewFilter().
|
||||||
// DeleteBucketEncryption
|
Queries("retention").
|
||||||
bucket.Methods(http.MethodDelete).HandlerFunc(
|
Handler(named("PutObjectRetention", h.PutObjectRetentionHandler))).
|
||||||
m.Handle(h.DeleteBucketEncryptionHandler)).
|
Add(NewFilter().
|
||||||
Queries("encryption", "").
|
Queries("legal-hold").
|
||||||
Name("DeleteBucketEncryption")
|
Handler(named("PutObjectLegalHold", h.PutObjectLegalHoldHandler))).
|
||||||
// DeleteBucket
|
DefaultHandler(named("PutObject", h.PutObjectHandler)))
|
||||||
bucket.Methods(http.MethodDelete).HandlerFunc(
|
})
|
||||||
m.Handle(h.DeleteBucketHandler)).
|
|
||||||
Name("DeleteBucket")
|
// POST method handlers
|
||||||
}
|
objRouter.Group(func(r chi.Router) {
|
||||||
// Root operation
|
r.Method(http.MethodPost, "/", NewHandlerFilter().
|
||||||
|
Add(NewFilter().
|
||||||
// ListBuckets
|
Queries("uploadId").
|
||||||
api.Methods(http.MethodGet).Path(SlashSeparator).HandlerFunc(
|
Handler(named("CompleteMultipartUpload", h.CompleteMultipartUploadHandler))).
|
||||||
m.Handle(h.ListBucketsHandler)).
|
Add(NewFilter().
|
||||||
Name("ListBuckets")
|
Queries("uploads").
|
||||||
|
Handler(named("CreateMultipartUpload", h.CreateMultipartUploadHandler))).
|
||||||
// S3 browser with signature v4 adds '//' for ListBuckets request, so rather
|
DefaultHandler(named("SelectObjectContent", h.SelectObjectContentHandler)))
|
||||||
// than failing with UnknownAPIRequest we simply handle it for now.
|
})
|
||||||
api.Methods(http.MethodGet).Path(SlashSeparator + SlashSeparator).HandlerFunc(
|
|
||||||
m.Handle(h.ListBucketsHandler)).
|
// DELETE method handlers
|
||||||
Name("ListBuckets")
|
objRouter.Group(func(r chi.Router) {
|
||||||
|
r.Method(http.MethodDelete, "/", NewHandlerFilter().
|
||||||
|
Add(NewFilter().
|
||||||
|
Queries("uploadId").
|
||||||
|
Handler(named("AbortMultipartUpload", h.AbortMultipartUploadHandler))).
|
||||||
|
Add(NewFilter().
|
||||||
|
Queries("tagging").
|
||||||
|
Handler(named("DeleteObjectTagging", h.DeleteObjectTaggingHandler))).
|
||||||
|
DefaultHandler(named("DeleteObject", h.DeleteObjectHandler)))
|
||||||
|
})
|
||||||
|
|
||||||
|
return objRouter
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
|
||||||
treepool "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool/tree"
|
treepool "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool/tree"
|
||||||
"github.com/gorilla/mux"
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
@ -58,7 +59,6 @@ type (
|
||||||
bucketResolver *resolver.BucketResolver
|
bucketResolver *resolver.BucketResolver
|
||||||
services []*Service
|
services []*Service
|
||||||
settings *appSettings
|
settings *appSettings
|
||||||
maxClients api.MaxClients
|
|
||||||
|
|
||||||
webDone chan struct{}
|
webDone chan struct{}
|
||||||
wrkDone chan struct{}
|
wrkDone chan struct{}
|
||||||
|
@ -68,6 +68,12 @@ type (
|
||||||
logLevel zap.AtomicLevel
|
logLevel zap.AtomicLevel
|
||||||
policies *placementPolicy
|
policies *placementPolicy
|
||||||
xmlDecoder *xml.DecoderProvider
|
xmlDecoder *xml.DecoderProvider
|
||||||
|
maxClient maxClientsConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
maxClientsConfig struct {
|
||||||
|
deadline time.Duration
|
||||||
|
count int
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger struct {
|
Logger struct {
|
||||||
|
@ -101,8 +107,7 @@ func newApp(ctx context.Context, log *Logger, v *viper.Viper) *App {
|
||||||
webDone: make(chan struct{}, 1),
|
webDone: make(chan struct{}, 1),
|
||||||
wrkDone: make(chan struct{}, 1),
|
wrkDone: make(chan struct{}, 1),
|
||||||
|
|
||||||
maxClients: newMaxClients(v),
|
settings: newAppSettings(log, v),
|
||||||
settings: newAppSettings(log, v),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.init(ctx)
|
app.init(ctx)
|
||||||
|
@ -161,6 +166,7 @@ func newAppSettings(log *Logger, v *viper.Viper) *appSettings {
|
||||||
logLevel: log.lvl,
|
logLevel: log.lvl,
|
||||||
policies: policies,
|
policies: policies,
|
||||||
xmlDecoder: xml.NewDecoderProvider(v.GetBool(cfgKludgeUseDefaultXMLNSForCompleteMultipartUpload)),
|
xmlDecoder: xml.NewDecoderProvider(v.GetBool(cfgKludgeUseDefaultXMLNSForCompleteMultipartUpload)),
|
||||||
|
maxClient: newMaxClients(v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,18 +248,20 @@ func (a *App) shutdownTracing() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMaxClients(cfg *viper.Viper) api.MaxClients {
|
func newMaxClients(cfg *viper.Viper) maxClientsConfig {
|
||||||
maxClientsCount := cfg.GetInt(cfgMaxClientsCount)
|
config := maxClientsConfig{}
|
||||||
if maxClientsCount <= 0 {
|
|
||||||
maxClientsCount = defaultMaxClientsCount
|
config.count = cfg.GetInt(cfgMaxClientsCount)
|
||||||
|
if config.count <= 0 {
|
||||||
|
config.count = defaultMaxClientsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
maxClientsDeadline := cfg.GetDuration(cfgMaxClientsDeadline)
|
config.deadline = cfg.GetDuration(cfgMaxClientsDeadline)
|
||||||
if maxClientsDeadline <= 0 {
|
if config.deadline <= 0 {
|
||||||
maxClientsDeadline = defaultMaxClientsDeadline
|
config.deadline = defaultMaxClientsDeadline
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.NewMaxClientsMiddleware(maxClientsCount, maxClientsDeadline)
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPools(ctx context.Context, logger *zap.Logger, cfg *viper.Viper) (*pool.Pool, *treepool.Pool, *keys.PrivateKey) {
|
func getPools(ctx context.Context, logger *zap.Logger, cfg *viper.Viper) (*pool.Pool, *treepool.Pool, *keys.PrivateKey) {
|
||||||
|
@ -490,12 +498,18 @@ func (a *App) Serve(ctx context.Context) {
|
||||||
// Attach S3 API:
|
// Attach S3 API:
|
||||||
domains := a.cfg.GetStringSlice(cfgListenDomains)
|
domains := a.cfg.GetStringSlice(cfgListenDomains)
|
||||||
a.log.Info("fetch domains, prepare to use API", zap.Strings("domains", domains))
|
a.log.Info("fetch domains, prepare to use API", zap.Strings("domains", domains))
|
||||||
router := mux.NewRouter().SkipClean(true).UseEncodedPath()
|
|
||||||
api.Attach(router, domains, a.maxClients, a.api, a.ctr, a.log, a.metrics)
|
throttleOps := middleware.ThrottleOpts{
|
||||||
|
Limit: a.settings.maxClient.count,
|
||||||
|
BacklogTimeout: a.settings.maxClient.deadline,
|
||||||
|
}
|
||||||
|
|
||||||
|
chiRouter := chi.NewRouter()
|
||||||
|
api.AttachChi(chiRouter, domains, throttleOps, a.api, a.ctr, a.log, a.metrics)
|
||||||
|
|
||||||
// Use mux.Router as http.Handler
|
// Use mux.Router as http.Handler
|
||||||
srv := new(http.Server)
|
srv := new(http.Server)
|
||||||
srv.Handler = router
|
srv.Handler = chiRouter
|
||||||
srv.ErrorLog = zap.NewStdLog(a.log)
|
srv.ErrorLog = zap.NewStdLog(a.log)
|
||||||
|
|
||||||
a.startServices()
|
a.startServices()
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
errorsFrost "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors"
|
errorsFrost "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/tree"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/tree"
|
||||||
|
@ -169,7 +169,7 @@ func (w *PoolWrapper) RemoveNode(ctx context.Context, bktInfo *data.BucketInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBearer(ctx context.Context, bktInfo *data.BucketInfo) []byte {
|
func getBearer(ctx context.Context, bktInfo *data.BucketInfo) []byte {
|
||||||
if bd, ok := ctx.Value(api.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil {
|
if bd, ok := ctx.Value(middleware.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil {
|
||||||
if bd.Gate.BearerToken != nil {
|
if bd.Gate.BearerToken != nil {
|
||||||
if bd.Gate.BearerToken.Impersonate() || bktInfo.Owner.Equals(bearer.ResolveIssuer(*bd.Gate.BearerToken)) {
|
if bd.Gate.BearerToken.Impersonate() || bktInfo.Owner.Equals(bearer.ResolveIssuer(*bd.Gate.BearerToken)) {
|
||||||
return bd.Gate.BearerToken.Marshal()
|
return bd.Gate.BearerToken.Marshal()
|
||||||
|
|
|
@ -9,9 +9,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
@ -1192,7 +1192,7 @@ func (c *Tree) getNode(ctx context.Context, bktInfo *data.BucketInfo, treeID str
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Tree) reqLogger(ctx context.Context) *zap.Logger {
|
func (c *Tree) reqLogger(ctx context.Context) *zap.Logger {
|
||||||
reqLogger := api.GetReqLog(ctx)
|
reqLogger := middleware.GetReqLog(ctx)
|
||||||
if reqLogger != nil {
|
if reqLogger != nil {
|
||||||
return reqLogger
|
return reqLogger
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue