Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
Denis Kirillov 2021-08-09 11:53:58 +03:00 committed by Kirillov Denis
parent f3a6636efd
commit d332096598
18 changed files with 163 additions and 128 deletions

View file

@ -14,6 +14,7 @@ import (
v4 "github.com/aws/aws-sdk-go/aws/signer/v4" v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neofs-api-go/pkg/object" "github.com/nspcc-dev/neofs-api-go/pkg/object"
apiErrors "github.com/nspcc-dev/neofs-s3-gw/api/errors"
"github.com/nspcc-dev/neofs-s3-gw/creds/accessbox" "github.com/nspcc-dev/neofs-s3-gw/creds/accessbox"
"github.com/nspcc-dev/neofs-s3-gw/creds/tokens" "github.com/nspcc-dev/neofs-s3-gw/creds/tokens"
"github.com/nspcc-dev/neofs-sdk-go/pkg/pool" "github.com/nspcc-dev/neofs-sdk-go/pkg/pool"
@ -77,7 +78,7 @@ func (c *center) Authenticate(r *http.Request) (*accessbox.Box, error) {
sms1 := c.reg.getSubmatches(authHeaderField[0]) sms1 := c.reg.getSubmatches(authHeaderField[0])
if len(sms1) != 7 { if len(sms1) != 7 {
return nil, errors.New("bad Authorization header field") return nil, apiErrors.GetAPIError(apiErrors.ErrAuthorizationHeaderMalformed)
} }
signedHeaderFieldsNames := strings.Split(sms1["signed_header_fields"], ";") signedHeaderFieldsNames := strings.Split(sms1["signed_header_fields"], ";")
@ -125,7 +126,7 @@ func (c *center) Authenticate(r *http.Request) (*accessbox.Box, error) {
sms2 := c.reg.getSubmatches(otherRequest.Header.Get("Authorization")) sms2 := c.reg.getSubmatches(otherRequest.Header.Get("Authorization"))
if sms1["v4_signature"] != sms2["v4_signature"] { if sms1["v4_signature"] != sms2["v4_signature"] {
return nil, errors.New("failed to pass authentication procedure") return nil, apiErrors.GetAPIError(apiErrors.ErrSignatureDoesNotMatch)
} }
return box, nil return box, nil

View file

@ -0,0 +1,16 @@
package auth
import (
"fmt"
"testing"
)
func TestName(t *testing.T) {
//target:= "AWS4-HMAC-SHA256 Credential=vWqF8cMDRbJcvnPLALoQGnABPPhw8NyYMcGsfDPfZJM0HrgjonN8CgFvCZ3kh9BUXw4W2tJ5E7EAGhueSF122HB/20210809/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=2811ccb9e242f41426738fb1fa6a456ef37c63505da1a160f3d76a4f51b17581"
target := "AWS4-HMAC-SHA256 Credential=badauth/20210809/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=2811ccb9e242f41426738fb1fa6a456ef37c63505da1a160f3d76a4f51b17581"
subMatcher := &regexpSubmatcher{re: authorizationFieldRegexp}
submatches := subMatcher.getSubmatches(target)
fmt.Println(submatches)
}

View file

@ -1,4 +1,4 @@
package api package errors
import ( import (
"fmt" "fmt"
@ -10,6 +10,14 @@ type (
ErrorCode int ErrorCode int
errorCodeMap map[ErrorCode]Error errorCodeMap map[ErrorCode]Error
// Error structure represents API error.
Error struct {
ErrCode ErrorCode
Code string
Description string
HTTPStatusCode int
}
) )
const maxEConfigJSONSize = 262272 const maxEConfigJSONSize = 262272
@ -1875,7 +1883,7 @@ func IsS3Error(err error, code ErrorCode) bool {
return ok && e.ErrCode == code return ok && e.ErrCode == code
} }
func (e errorCodeMap) ToAPIErrWithErr(errCode ErrorCode, err error) Error { func (e errorCodeMap) toAPIErrWithErr(errCode ErrorCode, err error) Error {
apiErr, ok := e[errCode] apiErr, ok := e[errCode]
if !ok { if !ok {
apiErr = e[ErrInternalError] apiErr = e[ErrInternalError]
@ -1886,8 +1894,8 @@ func (e errorCodeMap) ToAPIErrWithErr(errCode ErrorCode, err error) Error {
return apiErr return apiErr
} }
func (e errorCodeMap) ToAPIErr(errCode ErrorCode) Error { func (e errorCodeMap) toAPIErr(errCode ErrorCode) Error {
return e.ToAPIErrWithErr(errCode, nil) return e.toAPIErrWithErr(errCode, nil)
} }
func (e Error) Error() string { func (e Error) Error() string {
@ -1899,29 +1907,7 @@ func GetAPIError(code ErrorCode) Error {
if apiErr, ok := errorCodes[code]; ok { if apiErr, ok := errorCodes[code]; ok {
return apiErr return apiErr
} }
return errorCodes.ToAPIErr(ErrInternalError) return errorCodes.toAPIErr(ErrInternalError)
}
// getErrorResponse gets in standard error and resource value and
// provides a encodable populated response values.
func getAPIErrorResponse(info *ReqInfo, err error) ErrorResponse {
code := "InternalError"
desc := err.Error()
if e, ok := err.(Error); ok {
code = e.Code
desc = e.Description
}
return ErrorResponse{
Code: code,
Message: desc,
BucketName: info.BucketName,
Key: info.ObjectName,
Resource: info.URL.Path,
RequestID: info.RequestID,
HostID: info.DeploymentID,
}
} }
// GenericError - generic object layer error. // GenericError - generic object layer error.

View file

@ -1,4 +1,4 @@
package api package errors
import ( import (
"errors" "errors"

View file

@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
"github.com/nspcc-dev/neofs-s3-gw/api/layer" "github.com/nspcc-dev/neofs-s3-gw/api/layer"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -48,7 +49,7 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
// its non "null" value, we should error out since we do not support // its non "null" value, we should error out since we do not support
// any versions other than "null". // any versions other than "null".
if vid := u.Query().Get("versionId"); vid != "" && vid != "null" { if vid := u.Query().Get("versionId"); vid != "" && vid != "null" {
h.logAndSendError(w, "no such version", reqInfo, api.GetAPIError(api.ErrNoSuchVersion)) h.logAndSendError(w, "no such version", reqInfo, errors.GetAPIError(errors.ErrNoSuchVersion))
return return
} }
@ -66,7 +67,7 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
if args.MetadataDirective == replaceMetadataDirective { if args.MetadataDirective == replaceMetadataDirective {
metadata = parseMetadata(r) metadata = parseMetadata(r)
} else if srcBucket == reqInfo.BucketName && srcObject == reqInfo.ObjectName { } else if srcBucket == reqInfo.BucketName && srcObject == reqInfo.ObjectName {
h.logAndSendError(w, "could not copy to itself", reqInfo, api.GetAPIError(api.ErrInvalidRequest)) h.logAndSendError(w, "could not copy to itself", reqInfo, errors.GetAPIError(errors.ErrInvalidRequest))
return return
} }
@ -76,7 +77,7 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
} }
if err = checkPreconditions(inf, args.Conditional); err != nil { if err = checkPreconditions(inf, args.Conditional); err != nil {
h.logAndSendError(w, "precondition failed", reqInfo, api.GetAPIError(api.ErrPreconditionFailed)) h.logAndSendError(w, "precondition failed", reqInfo, errors.GetAPIError(errors.ErrPreconditionFailed))
return return
} }

View file

@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
"github.com/nspcc-dev/neofs-s3-gw/api/layer" "github.com/nspcc-dev/neofs-s3-gw/api/layer"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -69,14 +70,14 @@ func (h *handler) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Re
// Content-Md5 is requied should be set // Content-Md5 is requied should be set
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html // http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
if _, ok := r.Header[api.ContentMD5]; !ok { if _, ok := r.Header[api.ContentMD5]; !ok {
h.logAndSendError(w, "missing Content-MD5", reqInfo, api.GetAPIError(api.ErrMissingContentMD5)) h.logAndSendError(w, "missing Content-MD5", reqInfo, errors.GetAPIError(errors.ErrMissingContentMD5))
return return
} }
// Content-Length is required and should be non-zero // Content-Length is required and should be non-zero
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html // http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
if r.ContentLength <= 0 { if r.ContentLength <= 0 {
h.logAndSendError(w, "missing Content-Length", reqInfo, api.GetAPIError(api.ErrMissingContentLength)) h.logAndSendError(w, "missing Content-Length", reqInfo, errors.GetAPIError(errors.ErrMissingContentLength))
return return
} }
@ -107,7 +108,7 @@ func (h *handler) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Re
h.logAndSendError(w, "could not delete objects", reqInfo, nil, additional...) h.logAndSendError(w, "could not delete objects", reqInfo, nil, additional...)
for _, e := range errs { for _, e := range errs {
if err, ok := e.(*api.DeleteError); ok { if err, ok := e.(*errors.DeleteError); ok {
code := "BadRequest" code := "BadRequest"
desc := err.Error() desc := err.Error()

View file

@ -8,6 +8,7 @@ import (
"time" "time"
"github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
"github.com/nspcc-dev/neofs-s3-gw/api/layer" "github.com/nspcc-dev/neofs-s3-gw/api/layer"
) )
@ -29,7 +30,7 @@ func fetchRangeHeader(headers http.Header, fullSize uint64) (*layer.RangeParams,
return nil, nil return nil, nil
} }
if fullSize == 0 { if fullSize == 0 {
return nil, api.GetAPIError(api.ErrInvalidRange) return nil, errors.GetAPIError(errors.ErrInvalidRange)
} }
if !strings.HasPrefix(rangeHeader, prefix) { if !strings.HasPrefix(rangeHeader, prefix) {
return nil, fmt.Errorf("unknown unit in range header") return nil, fmt.Errorf("unknown unit in range header")
@ -59,7 +60,7 @@ func fetchRangeHeader(headers http.Header, fullSize uint64) (*layer.RangeParams,
} }
if err0 != nil || err1 != nil || start > end || start > fullSize { if err0 != nil || err1 != nil || start > end || start > fullSize {
return nil, api.GetAPIError(api.ErrInvalidRange) return nil, errors.GetAPIError(errors.ErrInvalidRange)
} }
return &layer.RangeParams{Start: start, End: end}, nil return &layer.RangeParams{Start: start, End: end}, nil
} }
@ -124,17 +125,17 @@ func (h *handler) GetObjectHandler(w http.ResponseWriter, r *http.Request) {
func checkPreconditions(inf *layer.ObjectInfo, args *conditionalArgs) error { func checkPreconditions(inf *layer.ObjectInfo, args *conditionalArgs) error {
if len(args.IfMatch) > 0 && args.IfMatch != inf.HashSum { if len(args.IfMatch) > 0 && args.IfMatch != inf.HashSum {
return api.GetAPIError(api.ErrPreconditionFailed) return errors.GetAPIError(errors.ErrPreconditionFailed)
} }
if len(args.IfNoneMatch) > 0 && args.IfNoneMatch == inf.HashSum { if len(args.IfNoneMatch) > 0 && args.IfNoneMatch == inf.HashSum {
return api.GetAPIError(api.ErrNotModified) return errors.GetAPIError(errors.ErrNotModified)
} }
if args.IfModifiedSince != nil && inf.Created.Before(*args.IfModifiedSince) { if args.IfModifiedSince != nil && inf.Created.Before(*args.IfModifiedSince) {
return api.GetAPIError(api.ErrNotModified) return errors.GetAPIError(errors.ErrNotModified)
} }
if args.IfUnmodifiedSince != nil && inf.Created.After(*args.IfUnmodifiedSince) { if args.IfUnmodifiedSince != nil && inf.Created.After(*args.IfUnmodifiedSince) {
if len(args.IfMatch) == 0 { if len(args.IfMatch) == 0 {
return api.GetAPIError(api.ErrPreconditionFailed) return errors.GetAPIError(errors.ErrPreconditionFailed)
} }
} }

View file

@ -5,7 +5,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api/errors"
"github.com/nspcc-dev/neofs-s3-gw/api/layer" "github.com/nspcc-dev/neofs-s3-gw/api/layer"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -80,7 +80,7 @@ func TestPreconditions(t *testing.T) {
name: "IfMatch false", name: "IfMatch false",
info: newInfo(etag, today), info: newInfo(etag, today),
args: &conditionalArgs{IfMatch: etag2}, args: &conditionalArgs{IfMatch: etag2},
expected: api.GetAPIError(api.ErrPreconditionFailed)}, expected: errors.GetAPIError(errors.ErrPreconditionFailed)},
{ {
name: "IfNoneMatch true", name: "IfNoneMatch true",
info: newInfo(etag, today), info: newInfo(etag, today),
@ -90,7 +90,7 @@ func TestPreconditions(t *testing.T) {
name: "IfNoneMatch false", name: "IfNoneMatch false",
info: newInfo(etag, today), info: newInfo(etag, today),
args: &conditionalArgs{IfNoneMatch: etag}, args: &conditionalArgs{IfNoneMatch: etag},
expected: api.GetAPIError(api.ErrNotModified)}, expected: errors.GetAPIError(errors.ErrNotModified)},
{ {
name: "IfModifiedSince true", name: "IfModifiedSince true",
info: newInfo(etag, today), info: newInfo(etag, today),
@ -100,7 +100,7 @@ func TestPreconditions(t *testing.T) {
name: "IfModifiedSince false", name: "IfModifiedSince false",
info: newInfo(etag, yesterday), info: newInfo(etag, yesterday),
args: &conditionalArgs{IfModifiedSince: &today}, args: &conditionalArgs{IfModifiedSince: &today},
expected: api.GetAPIError(api.ErrNotModified)}, expected: errors.GetAPIError(errors.ErrNotModified)},
{ {
name: "IfUnmodifiedSince true", name: "IfUnmodifiedSince true",
info: newInfo(etag, yesterday), info: newInfo(etag, yesterday),
@ -110,7 +110,7 @@ func TestPreconditions(t *testing.T) {
name: "IfUnmodifiedSince false", name: "IfUnmodifiedSince false",
info: newInfo(etag, today), info: newInfo(etag, today),
args: &conditionalArgs{IfUnmodifiedSince: &yesterday}, args: &conditionalArgs{IfUnmodifiedSince: &yesterday},
expected: api.GetAPIError(api.ErrPreconditionFailed)}, expected: errors.GetAPIError(errors.ErrPreconditionFailed)},
{ {
name: "IfMatch true, IfUnmodifiedSince false", name: "IfMatch true, IfUnmodifiedSince false",
@ -122,19 +122,19 @@ func TestPreconditions(t *testing.T) {
name: "IfMatch false, IfUnmodifiedSince true", name: "IfMatch false, IfUnmodifiedSince true",
info: newInfo(etag, yesterday), info: newInfo(etag, yesterday),
args: &conditionalArgs{IfMatch: etag2, IfUnmodifiedSince: &today}, args: &conditionalArgs{IfMatch: etag2, IfUnmodifiedSince: &today},
expected: api.GetAPIError(api.ErrPreconditionFailed), expected: errors.GetAPIError(errors.ErrPreconditionFailed),
}, },
{ {
name: "IfNoneMatch false, IfModifiedSince true", name: "IfNoneMatch false, IfModifiedSince true",
info: newInfo(etag, today), info: newInfo(etag, today),
args: &conditionalArgs{IfNoneMatch: etag, IfModifiedSince: &yesterday}, args: &conditionalArgs{IfNoneMatch: etag, IfModifiedSince: &yesterday},
expected: api.GetAPIError(api.ErrNotModified), expected: errors.GetAPIError(errors.ErrNotModified),
}, },
{ {
name: "IfNoneMatch true, IfModifiedSince false", name: "IfNoneMatch true, IfModifiedSince false",
info: newInfo(etag, yesterday), info: newInfo(etag, yesterday),
args: &conditionalArgs{IfNoneMatch: etag2, IfModifiedSince: &today}, args: &conditionalArgs{IfNoneMatch: etag2, IfModifiedSince: &today},
expected: api.GetAPIError(api.ErrNotModified), expected: errors.GetAPIError(errors.ErrNotModified),
}, },
} { } {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {

View file

@ -4,28 +4,29 @@ import (
"net/http" "net/http"
"github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
) )
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()), api.GetAPIError(api.ErrNotSupported)) h.logAndSendError(w, "not supported", api.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()), api.GetAPIError(api.ErrNotSupported)) h.logAndSendError(w, "not supported", api.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()), api.GetAPIError(api.ErrNotSupported)) h.logAndSendError(w, "not supported", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotSupported))
} }
func (h *handler) PutBucketTaggingHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PutBucketTaggingHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not supported", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotSupported)) h.logAndSendError(w, "not supported", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotSupported))
} }
func (h *handler) PutBucketVersioningHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PutBucketVersioningHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not supported", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotSupported)) h.logAndSendError(w, "not supported", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotSupported))
} }
func (h *handler) PutBucketNotificationHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PutBucketNotificationHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not supported", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotSupported)) h.logAndSendError(w, "not supported", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotSupported))
} }

View file

@ -8,6 +8,7 @@ import (
"github.com/nspcc-dev/neofs-api-go/pkg/object" "github.com/nspcc-dev/neofs-api-go/pkg/object"
"github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
"github.com/nspcc-dev/neofs-s3-gw/api/layer" "github.com/nspcc-dev/neofs-s3-gw/api/layer"
) )
@ -144,7 +145,7 @@ func parseListObjectArgs(reqInfo *api.ReqInfo) (*layer.ListObjectsParamsCommon,
if queryValues.Get("max-keys") == "" { if queryValues.Get("max-keys") == "" {
res.MaxKeys = maxObjectList res.MaxKeys = maxObjectList
} else if res.MaxKeys, err = strconv.Atoi(queryValues.Get("max-keys")); err != nil || res.MaxKeys < 0 { } else if res.MaxKeys, err = strconv.Atoi(queryValues.Get("max-keys")); err != nil || res.MaxKeys < 0 {
return nil, api.GetAPIError(api.ErrInvalidMaxKeys) return nil, errors.GetAPIError(errors.ErrInvalidMaxKeys)
} }
res.Prefix = queryValues.Get("prefix") res.Prefix = queryValues.Get("prefix")
@ -155,7 +156,7 @@ func parseListObjectArgs(reqInfo *api.ReqInfo) (*layer.ListObjectsParamsCommon,
func parseContinuationToken(queryValues url.Values) (string, error) { func parseContinuationToken(queryValues url.Values) (string, error) {
if val, ok := queryValues["continuation-token"]; ok { if val, ok := queryValues["continuation-token"]; ok {
if err := object.NewID().Parse(val[0]); err != nil { if err := object.NewID().Parse(val[0]); err != nil {
return "", api.GetAPIError(api.ErrIncorrectContinuationToken) return "", errors.GetAPIError(errors.ErrIncorrectContinuationToken)
} }
return val[0], nil return val[0], nil
} }
@ -228,7 +229,7 @@ func parseListObjectVersionsRequest(reqInfo *api.ReqInfo) (*layer.ListObjectVers
if queryValues.Get("max-keys") == "" { if queryValues.Get("max-keys") == "" {
res.MaxKeys = maxObjectList res.MaxKeys = maxObjectList
} else if res.MaxKeys, err = strconv.Atoi(queryValues.Get("max-keys")); err != nil || res.MaxKeys <= 0 { } else if res.MaxKeys, err = strconv.Atoi(queryValues.Get("max-keys")); err != nil || res.MaxKeys <= 0 {
return nil, api.GetAPIError(api.ErrInvalidMaxKeys) return nil, errors.GetAPIError(errors.ErrInvalidMaxKeys)
} }
res.Prefix = queryValues.Get("prefix") res.Prefix = queryValues.Get("prefix")

View file

@ -8,6 +8,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
"github.com/nspcc-dev/neofs-api-go/pkg/acl" "github.com/nspcc-dev/neofs-api-go/pkg/acl"
"github.com/nspcc-dev/neofs-node/pkg/policy" "github.com/nspcc-dev/neofs-node/pkg/policy"
"github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api"
@ -135,27 +137,27 @@ func (h *handler) CreateBucketHandler(w http.ResponseWriter, r *http.Request) {
func checkBucketName(bucketName string) error { func checkBucketName(bucketName string) error {
if len(bucketName) < 3 || len(bucketName) > 63 { if len(bucketName) < 3 || len(bucketName) > 63 {
return api.GetAPIError(api.ErrInvalidBucketName) return errors.GetAPIError(errors.ErrInvalidBucketName)
} }
if strings.HasPrefix(bucketName, "xn--") || strings.HasSuffix(bucketName, "-s3alias") { if strings.HasPrefix(bucketName, "xn--") || strings.HasSuffix(bucketName, "-s3alias") {
return api.GetAPIError(api.ErrInvalidBucketName) return errors.GetAPIError(errors.ErrInvalidBucketName)
} }
if net.ParseIP(bucketName) != nil { if net.ParseIP(bucketName) != nil {
return api.GetAPIError(api.ErrInvalidBucketName) return errors.GetAPIError(errors.ErrInvalidBucketName)
} }
labels := strings.Split(bucketName, ".") labels := strings.Split(bucketName, ".")
for _, label := range labels { for _, label := range labels {
if len(label) == 0 { if len(label) == 0 {
return api.GetAPIError(api.ErrInvalidBucketName) return errors.GetAPIError(errors.ErrInvalidBucketName)
} }
for i, r := range label { for i, r := range label {
if !isAlphaNum(r) && r != '-' { if !isAlphaNum(r) && r != '-' {
return api.GetAPIError(api.ErrInvalidBucketName) return errors.GetAPIError(errors.ErrInvalidBucketName)
} }
if (i == 0 || i == len(label)-1) && r == '-' { if (i == 0 || i == len(label)-1) && r == '-' {
return api.GetAPIError(api.ErrInvalidBucketName) return errors.GetAPIError(errors.ErrInvalidBucketName)
} }
} }
} }

View file

@ -4,160 +4,161 @@ import (
"net/http" "net/http"
"github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
) )
func (h *handler) CopyObjectPartHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) CopyObjectPartHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) PutObjectPartHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PutObjectPartHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) ListObjectPartsHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) ListObjectPartsHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) NewMultipartUploadHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) NewMultipartUploadHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) AbortMultipartUploadHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) AbortMultipartUploadHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) GetObjectACLHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) GetObjectACLHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) GetObjectTaggingHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) GetObjectTaggingHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) PutObjectTaggingHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PutObjectTaggingHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) DeleteObjectTaggingHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) DeleteObjectTaggingHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) GetObjectRetentionHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) GetObjectRetentionHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) GetObjectLegalHoldHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) GetObjectLegalHoldHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) PutObjectRetentionHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PutObjectRetentionHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) PutObjectLegalHoldHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PutObjectLegalHoldHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) GetBucketPolicyHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) GetBucketPolicyHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) PutBucketACLHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PutBucketACLHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) GetBucketCorsHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) GetBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) GetBucketTaggingHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) GetBucketTaggingHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) DeleteBucketTaggingHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) DeleteBucketTaggingHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) GetBucketObjectLockConfigHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) GetBucketObjectLockConfigHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) GetBucketNotificationHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) GetBucketNotificationHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.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()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) PutBucketObjectLockConfigHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PutBucketObjectLockConfigHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }
func (h *handler) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Request) {
h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), api.GetAPIError(api.ErrNotImplemented)) h.logAndSendError(w, "not implemented", api.GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrNotImplemented))
} }

View file

@ -15,6 +15,7 @@ import (
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id" cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
"github.com/nspcc-dev/neofs-api-go/pkg/owner" "github.com/nspcc-dev/neofs-api-go/pkg/owner"
"github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
"github.com/nspcc-dev/neofs-sdk-go/pkg/pool" "github.com/nspcc-dev/neofs-sdk-go/pkg/pool"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -49,7 +50,7 @@ func (n *layer) containerInfo(ctx context.Context, cid *cid.ID) (*BucketInfo, er
zap.Error(err)) zap.Error(err))
if strings.Contains(err.Error(), "container not found") { if strings.Contains(err.Error(), "container not found") {
return nil, api.GetAPIError(api.ErrNoSuchBucket) return nil, errors.GetAPIError(errors.ErrNoSuchBucket)
} }
return nil, err return nil, err
} }

View file

@ -15,6 +15,7 @@ import (
"github.com/nspcc-dev/neofs-api-go/pkg/object" "github.com/nspcc-dev/neofs-api-go/pkg/object"
"github.com/nspcc-dev/neofs-api-go/pkg/owner" "github.com/nspcc-dev/neofs-api-go/pkg/owner"
"github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
"github.com/nspcc-dev/neofs-s3-gw/creds/accessbox" "github.com/nspcc-dev/neofs-s3-gw/creds/accessbox"
"github.com/nspcc-dev/neofs-sdk-go/pkg/pool" "github.com/nspcc-dev/neofs-sdk-go/pkg/pool"
"go.uber.org/zap" "go.uber.org/zap"
@ -187,7 +188,7 @@ func (n *layer) GetBucketInfo(ctx context.Context, name string) (*BucketInfo, er
} }
} }
return nil, api.GetAPIError(api.ErrNoSuchBucket) return nil, errors.GetAPIError(errors.ErrNoSuchBucket)
} }
return n.containerInfo(ctx, containerID) return n.containerInfo(ctx, containerID)
@ -246,7 +247,7 @@ func (n *layer) checkObject(ctx context.Context, cid *cid.ID, filename string) e
var err error var err error
if _, err = n.objectFindID(ctx, &findParams{cid: cid, val: filename}); err == nil { if _, err = n.objectFindID(ctx, &findParams{cid: cid, val: filename}); err == nil {
return new(api.ObjectAlreadyExists) return new(errors.ObjectAlreadyExists)
} }
return err return err
@ -320,12 +321,12 @@ func (n *layer) DeleteObject(ctx context.Context, bucket, filename string) error
) )
if bkt, err = n.GetBucketInfo(ctx, bucket); err != nil { if bkt, err = n.GetBucketInfo(ctx, bucket); err != nil {
return &api.DeleteError{ return &errors.DeleteError{
Err: err, Err: err,
Object: filename, Object: filename,
} }
} else if ids, err = n.objectSearch(ctx, &findParams{cid: bkt.CID, val: filename}); err != nil { } else if ids, err = n.objectSearch(ctx, &findParams{cid: bkt.CID, val: filename}); err != nil {
return &api.DeleteError{ return &errors.DeleteError{
Err: err, Err: err,
Object: filename, Object: filename,
} }
@ -337,7 +338,7 @@ func (n *layer) DeleteObject(ctx context.Context, bucket, filename string) error
addr.SetContainerID(bkt.CID) addr.SetContainerID(bkt.CID)
if err = n.objectDelete(ctx, addr); err != nil { if err = n.objectDelete(ctx, addr); err != nil {
return &api.DeleteError{ return &errors.DeleteError{
Err: err, Err: err,
Object: filename, Object: filename,
} }
@ -363,13 +364,13 @@ func (n *layer) DeleteObjects(ctx context.Context, bucket string, objects []stri
func (n *layer) CreateBucket(ctx context.Context, p *CreateBucketParams) (*cid.ID, error) { func (n *layer) CreateBucket(ctx context.Context, p *CreateBucketParams) (*cid.ID, error) {
_, err := n.GetBucketInfo(ctx, p.Name) _, err := n.GetBucketInfo(ctx, p.Name)
if err != nil { if err != nil {
if api.IsS3Error(err, api.ErrNoSuchBucket) { if errors.IsS3Error(err, errors.ErrNoSuchBucket) {
return n.createContainer(ctx, p) return n.createContainer(ctx, p)
} }
return nil, err return nil, err
} }
return nil, api.GetAPIError(api.ErrBucketAlreadyExists) return nil, errors.GetAPIError(errors.ErrBucketAlreadyExists)
} }
func (n *layer) DeleteBucket(ctx context.Context, p *DeleteBucketParams) error { func (n *layer) DeleteBucket(ctx context.Context, p *DeleteBucketParams) error {

View file

@ -12,7 +12,7 @@ import (
"github.com/nspcc-dev/neofs-api-go/pkg/client" "github.com/nspcc-dev/neofs-api-go/pkg/client"
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id" cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
"github.com/nspcc-dev/neofs-api-go/pkg/object" "github.com/nspcc-dev/neofs-api-go/pkg/object"
"github.com/nspcc-dev/neofs-s3-gw/api" apiErrors "github.com/nspcc-dev/neofs-s3-gw/api/errors"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -81,7 +81,7 @@ func (n *layer) objectFindID(ctx context.Context, p *findParams) (*object.ID, er
if result, err := n.objectSearch(ctx, p); err != nil { if result, err := n.objectSearch(ctx, p); err != nil {
return nil, err return nil, err
} else if ln := len(result); ln == 0 { } else if ln := len(result); ln == 0 {
return nil, api.GetAPIError(api.ErrNoSuchKey) return nil, apiErrors.GetAPIError(apiErrors.ErrNoSuchKey)
} else if ln == 1 { } else if ln == 1 {
return result[0], nil return result[0], nil
} }
@ -124,14 +124,14 @@ func (n *layer) objectPut(ctx context.Context, p *PutObjectParams) (*ObjectInfo,
} else if bkt, err = n.GetBucketInfo(ctx, p.Bucket); err != nil { } else if bkt, err = n.GetBucketInfo(ctx, p.Bucket); err != nil {
return nil, err return nil, err
} else if err = n.checkObject(ctx, bkt.CID, p.Object); err != nil { } else if err = n.checkObject(ctx, bkt.CID, p.Object); err != nil {
var errExist *api.ObjectAlreadyExists var errExist *apiErrors.ObjectAlreadyExists
if ok := errors.As(err, &errExist); ok { if ok := errors.As(err, &errExist); ok {
errExist.Bucket = p.Bucket errExist.Bucket = p.Bucket
errExist.Object = p.Object errExist.Object = p.Object
return nil, errExist return nil, errExist
} }
if !api.IsS3Error(err, api.ErrNoSuchKey) { if !apiErrors.IsS3Error(err, apiErrors.ErrNoSuchKey) {
return nil, err return nil, err
} }
} }

View file

@ -3,6 +3,8 @@ package api
import ( import (
"net/http" "net/http"
"time" "time"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
) )
type ( type (
@ -49,7 +51,7 @@ func (m *maxClients) Handle(f http.HandlerFunc) http.HandlerFunc {
f.ServeHTTP(w, r) f.ServeHTTP(w, r)
case <-deadline.C: case <-deadline.C:
// Send a http timeout message // Send a http timeout message
WriteErrorResponse(w, GetReqInfo(r.Context()), errorCodes.ToAPIErr(ErrOperationMaxedOut)) WriteErrorResponse(w, GetReqInfo(r.Context()), errors.GetAPIError(errors.ErrOperationTimedOut))
return return
case <-r.Context().Done(): case <-r.Context().Done():
return return

View file

@ -7,6 +7,8 @@ import (
"net/http" "net/http"
"strconv" "strconv"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/nspcc-dev/neofs-s3-gw/internal/version" "github.com/nspcc-dev/neofs-s3-gw/internal/version"
) )
@ -33,14 +35,6 @@ type (
// Underlying HTTP status code for the returned error. // Underlying HTTP status code for the returned error.
StatusCode int `xml:"-" json:"-"` StatusCode int `xml:"-" json:"-"`
} }
// Error structure represents API error.
Error struct {
ErrCode ErrorCode
Code string
Description string
HTTPStatusCode int
}
) )
const ( const (
@ -120,7 +114,7 @@ var s3ErrorResponseMap = map[string]string{
func WriteErrorResponse(w http.ResponseWriter, reqInfo *ReqInfo, err error) { func WriteErrorResponse(w http.ResponseWriter, reqInfo *ReqInfo, err error) {
code := http.StatusInternalServerError code := http.StatusInternalServerError
if e, ok := err.(Error); ok { if e, ok := err.(errors.Error); ok {
code = e.HTTPStatusCode code = e.HTTPStatusCode
switch e.Code { switch e.Code {
@ -142,7 +136,7 @@ func WriteErrorResponse(w http.ResponseWriter, reqInfo *ReqInfo, err error) {
// If none of the http routes match respond with appropriate errors. // If none of the http routes match respond with appropriate errors.
func errorResponseHandler(w http.ResponseWriter, r *http.Request) { func errorResponseHandler(w http.ResponseWriter, r *http.Request) {
desc := fmt.Sprintf("Unknown API request at %s", r.URL.Path) desc := fmt.Sprintf("Unknown API request at %s", r.URL.Path)
WriteErrorResponse(w, GetReqInfo(r.Context()), Error{ WriteErrorResponse(w, GetReqInfo(r.Context()), errors.Error{
Code: "XMinioUnknownAPIRequest", Code: "XMinioUnknownAPIRequest",
Description: desc, Description: desc,
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
@ -230,3 +224,25 @@ func (e ErrorResponse) Error() string {
} }
return e.Message return e.Message
} }
// getErrorResponse gets in standard error and resource value and
// provides a 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
}
return ErrorResponse{
Code: code,
Message: desc,
BucketName: info.BucketName,
Key: info.ObjectName,
Resource: info.URL.Path,
RequestID: info.RequestID,
HostID: info.DeploymentID,
}
}

View file

@ -6,6 +6,7 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/nspcc-dev/neofs-s3-gw/api/auth" "github.com/nspcc-dev/neofs-s3-gw/api/auth"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -27,7 +28,10 @@ func AttachUserAuth(router *mux.Router, center auth.Center, log *zap.Logger) {
ctx = r.Context() ctx = r.Context()
} else { } else {
log.Error("failed to pass authentication", zap.Error(err)) log.Error("failed to pass authentication", zap.Error(err))
WriteErrorResponse(w, GetReqInfo(r.Context()), GetAPIError(ErrAccessDenied)) if _, ok := err.(errors.Error); !ok {
err = errors.GetAPIError(errors.ErrAccessDenied)
}
WriteErrorResponse(w, GetReqInfo(r.Context()), err)
return return
} }
} else { } else {