mirror of
https://github.com/versity/versitygw.git
synced 2026-09-04 07:06:59 +00:00
feat: implements advanced routing for object GET actions.
This commit is contained in:
@@ -19,7 +19,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -73,605 +72,6 @@ func New(be backend.Backend, iam auth.IAMService, logger s3log.AuditLogger, evs
|
||||
}
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetActions(ctx *fiber.Ctx) error {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := ctx.Params("key")
|
||||
keyEnd := ctx.Params("*1")
|
||||
uploadId := ctx.Query("uploadId")
|
||||
partNumberMarker := ctx.Query("part-number-marker")
|
||||
acceptRange := ctx.Get("Range")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
versionId := ctx.Query("versionId")
|
||||
if keyEnd != "" {
|
||||
key = strings.Join([]string{key, keyEnd}, "/")
|
||||
}
|
||||
path := ctx.Path()
|
||||
if path[len(path)-1:] == "/" && key[len(key)-1:] != "/" {
|
||||
key = key + "/"
|
||||
}
|
||||
|
||||
if ctx.Request().URI().QueryArgs().Has("tagging") {
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
IsRoot: isRoot,
|
||||
Acc: acct,
|
||||
Bucket: bucket,
|
||||
Object: key,
|
||||
Action: auth.GetObjectTaggingAction,
|
||||
IsBucketPublic: isPublicBucket,
|
||||
})
|
||||
if err != nil {
|
||||
return SendXMLResponse(ctx, nil, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectTagging,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
tags, err := c.be.GetObjectTagging(ctx.Context(), bucket, key)
|
||||
if err != nil {
|
||||
return SendXMLResponse(ctx, nil, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectTagging,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
res := s3response.Tagging{
|
||||
TagSet: s3response.TagSet{Tags: []s3response.Tag{}},
|
||||
}
|
||||
|
||||
for key, val := range tags {
|
||||
res.TagSet.Tags = append(res.TagSet.Tags,
|
||||
s3response.Tag{Key: key, Value: val})
|
||||
}
|
||||
|
||||
return SendXMLResponse(ctx, res, nil,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectTagging,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
if ctx.Request().URI().QueryArgs().Has("retention") {
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
IsRoot: isRoot,
|
||||
Acc: acct,
|
||||
Bucket: bucket,
|
||||
Object: key,
|
||||
Action: auth.GetObjectRetentionAction,
|
||||
IsBucketPublic: isPublicBucket,
|
||||
})
|
||||
if err != nil {
|
||||
return SendXMLResponse(ctx, nil, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectRetention,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
data, err := c.be.GetObjectRetention(ctx.Context(), bucket, key, versionId)
|
||||
if err != nil {
|
||||
return SendXMLResponse(ctx, data, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectRetention,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
retention, err := auth.ParseObjectLockRetentionOutput(data)
|
||||
return SendXMLResponse(ctx, retention, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectRetention,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
if ctx.Request().URI().QueryArgs().Has("legal-hold") {
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
IsRoot: isRoot,
|
||||
Acc: acct,
|
||||
Bucket: bucket,
|
||||
Object: key,
|
||||
Action: auth.GetObjectLegalHoldAction,
|
||||
IsBucketPublic: isPublicBucket,
|
||||
})
|
||||
if err != nil {
|
||||
return SendXMLResponse(ctx, nil, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectLegalHold,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
data, err := c.be.GetObjectLegalHold(ctx.Context(), bucket, key, versionId)
|
||||
return SendXMLResponse(ctx, auth.ParseObjectLegalHoldOutput(data), err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectLegalHold,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
if uploadId != "" {
|
||||
if partNumberMarker != "" {
|
||||
n, err := strconv.Atoi(partNumberMarker)
|
||||
if err != nil || n < 0 {
|
||||
if err != nil && c.debug {
|
||||
debuglogger.Logf("error parsing part number marker %q: %v",
|
||||
partNumberMarker, err)
|
||||
}
|
||||
return SendResponse(ctx,
|
||||
s3err.GetAPIError(s3err.ErrInvalidPartNumberMarker),
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionListParts,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
}
|
||||
mxParts := ctx.Query("max-parts")
|
||||
maxParts, err := utils.ParseUint(mxParts)
|
||||
if err != nil {
|
||||
if c.debug {
|
||||
debuglogger.Logf("error parsing max parts %q: %v",
|
||||
mxParts, err)
|
||||
}
|
||||
return SendResponse(ctx,
|
||||
s3err.GetAPIError(s3err.ErrInvalidMaxParts),
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionListParts,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
err = auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
IsRoot: isRoot,
|
||||
Acc: acct,
|
||||
Bucket: bucket,
|
||||
Object: key,
|
||||
Action: auth.ListMultipartUploadPartsAction,
|
||||
IsBucketPublic: isPublicBucket,
|
||||
})
|
||||
if err != nil {
|
||||
return SendXMLResponse(ctx, nil, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionListParts,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
res, err := c.be.ListParts(ctx.Context(), &s3.ListPartsInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
UploadId: &uploadId,
|
||||
PartNumberMarker: &partNumberMarker,
|
||||
MaxParts: &maxParts,
|
||||
})
|
||||
return SendXMLResponse(ctx, res, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionListParts,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
if ctx.Request().URI().QueryArgs().Has("acl") {
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionReadAcp,
|
||||
IsRoot: isRoot,
|
||||
Acc: acct,
|
||||
Bucket: bucket,
|
||||
Object: key,
|
||||
Action: auth.GetObjectAclAction,
|
||||
IsBucketPublic: isPublicBucket,
|
||||
})
|
||||
if err != nil {
|
||||
return SendXMLResponse(ctx, nil, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectAcl,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
res, err := c.be.GetObjectAcl(ctx.Context(), &s3.GetObjectAclInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
})
|
||||
return SendXMLResponse(ctx, res, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectAcl,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
if ctx.Request().URI().QueryArgs().Has("attributes") {
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
IsRoot: isRoot,
|
||||
Acc: acct,
|
||||
Bucket: bucket,
|
||||
Object: key,
|
||||
Action: auth.GetObjectAttributesAction,
|
||||
IsBucketPublic: isPublicBucket,
|
||||
})
|
||||
if err != nil {
|
||||
return SendXMLResponse(ctx, nil, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectAttributes,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
maxParts := ctx.Get("X-Amz-Max-Parts")
|
||||
partNumberMarker := ctx.Get("X-Amz-Part-Number-Marker")
|
||||
maxPartsParsed, err := utils.ParseUint(maxParts)
|
||||
if err != nil {
|
||||
if c.debug {
|
||||
debuglogger.Logf("error parsing max parts %q: %v",
|
||||
maxParts, err)
|
||||
}
|
||||
return SendXMLResponse(ctx, nil, s3err.GetAPIError(s3err.ErrInvalidMaxParts),
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectAttributes,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
attrs, err := utils.ParseObjectAttributes(ctx)
|
||||
if err != nil {
|
||||
return SendXMLResponse(ctx, nil, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectAttributes,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
res, err := c.be.GetObjectAttributes(ctx.Context(),
|
||||
&s3.GetObjectAttributesInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
PartNumberMarker: &partNumberMarker,
|
||||
MaxParts: &maxPartsParsed,
|
||||
VersionId: &versionId,
|
||||
})
|
||||
if err != nil {
|
||||
hdrs := []utils.CustomHeader{}
|
||||
|
||||
if res.DeleteMarker != nil {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "x-amz-delete-marker",
|
||||
Value: "true",
|
||||
})
|
||||
}
|
||||
if getstring(res.VersionId) != "" {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "x-amz-version-id",
|
||||
Value: getstring(res.VersionId),
|
||||
})
|
||||
}
|
||||
|
||||
utils.SetResponseHeaders(ctx, hdrs)
|
||||
return SendXMLResponse(ctx, nil, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectAttributes,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
hdrs := []utils.CustomHeader{}
|
||||
|
||||
if getstring(res.VersionId) != "" {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "x-amz-version-id",
|
||||
Value: getstring(res.VersionId),
|
||||
})
|
||||
}
|
||||
if res.DeleteMarker != nil && *res.DeleteMarker {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "x-amz-delete-marker",
|
||||
Value: "true",
|
||||
})
|
||||
}
|
||||
if res.LastModified != nil {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "Last-Modified",
|
||||
Value: res.LastModified.UTC().Format(iso8601TimeFormatExtended),
|
||||
})
|
||||
}
|
||||
|
||||
utils.SetResponseHeaders(ctx, hdrs)
|
||||
|
||||
return SendXMLResponse(ctx, utils.FilterObjectAttributes(attrs, res), nil,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObjectAttributes,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
action := auth.GetObjectAction
|
||||
if versionId != "" {
|
||||
action = auth.GetObjectVersionAction
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
IsRoot: isRoot,
|
||||
Acc: acct,
|
||||
Bucket: bucket,
|
||||
Object: key,
|
||||
Action: action,
|
||||
IsBucketPublic: isPublicBucket,
|
||||
})
|
||||
if err != nil {
|
||||
return SendResponse(ctx, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObject,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
checksumMode := types.ChecksumMode(ctx.Get("x-amz-checksum-mode"))
|
||||
if checksumMode != "" && checksumMode != types.ChecksumModeEnabled {
|
||||
if c.debug {
|
||||
debuglogger.Logf("invalid x-amz-checksum-mode header value: %v", checksumMode)
|
||||
}
|
||||
return SendResponse(ctx, s3err.GetInvalidChecksumHeaderErr("x-amz-checksum-mode"),
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObject,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
utils.ContextKeySkipResBodyLog.Set(ctx, true)
|
||||
res, err := c.be.GetObject(ctx.Context(), &s3.GetObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
Range: &acceptRange,
|
||||
VersionId: &versionId,
|
||||
ChecksumMode: checksumMode,
|
||||
})
|
||||
if err != nil {
|
||||
if res != nil {
|
||||
utils.SetResponseHeaders(ctx, []utils.CustomHeader{
|
||||
{
|
||||
Key: "x-amz-delete-marker",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "Last-Modified",
|
||||
Value: res.LastModified.UTC().Format(timefmt),
|
||||
},
|
||||
})
|
||||
}
|
||||
return SendResponse(ctx, err,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionHeadObject,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
|
||||
contentType := getstring(res.ContentType)
|
||||
if contentType == "" {
|
||||
contentType = defaultContentType
|
||||
}
|
||||
acceptRanges := getstring(res.AcceptRanges)
|
||||
if acceptRanges == "" {
|
||||
acceptRanges = "bytes"
|
||||
}
|
||||
|
||||
hdrs := []utils.CustomHeader{
|
||||
{
|
||||
Key: "Content-Type",
|
||||
Value: contentType,
|
||||
},
|
||||
{
|
||||
Key: "ETag",
|
||||
Value: getstring(res.ETag),
|
||||
},
|
||||
{
|
||||
Key: "accept-ranges",
|
||||
Value: acceptRanges,
|
||||
},
|
||||
}
|
||||
if getstring(res.ContentDisposition) != "" {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "Content-Disposition",
|
||||
Value: getstring(res.ContentDisposition),
|
||||
})
|
||||
}
|
||||
if getstring(res.ContentEncoding) != "" {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "Content-Encoding",
|
||||
Value: getstring(res.ContentEncoding),
|
||||
})
|
||||
}
|
||||
if getstring(res.ContentLanguage) != "" {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "Content-Language",
|
||||
Value: getstring(res.ContentLanguage),
|
||||
})
|
||||
}
|
||||
if getstring(res.CacheControl) != "" {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "Cache-Control",
|
||||
Value: getstring(res.CacheControl),
|
||||
})
|
||||
}
|
||||
if getstring(res.ExpiresString) != "" {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "Expires",
|
||||
Value: getstring(res.ExpiresString),
|
||||
})
|
||||
}
|
||||
if getstring(res.ContentRange) != "" {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "Content-Range",
|
||||
Value: getstring(res.ContentRange),
|
||||
})
|
||||
}
|
||||
if res.LastModified != nil {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "Last-Modified",
|
||||
Value: res.LastModified.UTC().Format(timefmt),
|
||||
})
|
||||
}
|
||||
if res.TagCount != nil {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "x-amz-tagging-count",
|
||||
Value: fmt.Sprint(*res.TagCount),
|
||||
})
|
||||
}
|
||||
if res.StorageClass != "" {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "x-amz-storage-class",
|
||||
Value: string(res.StorageClass),
|
||||
})
|
||||
}
|
||||
if res.ChecksumCRC32 != nil {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "x-amz-checksum-crc32",
|
||||
Value: *res.ChecksumCRC32,
|
||||
})
|
||||
}
|
||||
if res.ChecksumCRC32C != nil {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "x-amz-checksum-crc32c",
|
||||
Value: *res.ChecksumCRC32C,
|
||||
})
|
||||
}
|
||||
if res.ChecksumSHA1 != nil {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "x-amz-checksum-sha1",
|
||||
Value: *res.ChecksumSHA1,
|
||||
})
|
||||
}
|
||||
if res.ChecksumSHA256 != nil {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "x-amz-checksum-sha256",
|
||||
Value: *res.ChecksumSHA256,
|
||||
})
|
||||
}
|
||||
if res.ChecksumCRC64NVME != nil {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "x-amz-checksum-crc64nvme",
|
||||
Value: *res.ChecksumCRC64NVME,
|
||||
})
|
||||
}
|
||||
if res.ChecksumType != "" {
|
||||
hdrs = append(hdrs, utils.CustomHeader{
|
||||
Key: "x-amz-checksum-type",
|
||||
Value: string(res.ChecksumType),
|
||||
})
|
||||
}
|
||||
|
||||
// Set x-amz-meta-... headers
|
||||
utils.SetMetaHeaders(ctx, res.Metadata)
|
||||
// Set other response headers
|
||||
utils.SetResponseHeaders(ctx, hdrs)
|
||||
// Set version id header
|
||||
if getstring(res.VersionId) != "" {
|
||||
utils.SetResponseHeaders(ctx, []utils.CustomHeader{
|
||||
{
|
||||
Key: "x-amz-version-id",
|
||||
Value: getstring(res.VersionId),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
status := http.StatusOK
|
||||
if acceptRange != "" {
|
||||
status = http.StatusPartialContent
|
||||
}
|
||||
|
||||
if res.Body != nil {
|
||||
// -1 will stream response body until EOF if content length not set
|
||||
contentLen := -1
|
||||
if res.ContentLength != nil {
|
||||
if *res.ContentLength > int64(math.MaxInt) {
|
||||
debuglogger.Logf("content length %v int overflow",
|
||||
*res.ContentLength)
|
||||
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidRange),
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObject,
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
})
|
||||
}
|
||||
contentLen = int(*res.ContentLength)
|
||||
}
|
||||
utils.StreamResponseBody(ctx, res.Body, contentLen)
|
||||
}
|
||||
|
||||
return SendResponse(ctx, nil,
|
||||
&MetaOpts{
|
||||
Logger: c.logger,
|
||||
MetricsMng: c.mm,
|
||||
Action: metrics.ActionGetObject,
|
||||
ContentLength: getint64(res.ContentLength),
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
Status: status,
|
||||
})
|
||||
}
|
||||
|
||||
func getstring(s *string) string {
|
||||
if s == nil {
|
||||
return ""
|
||||
|
||||
Reference in New Issue
Block a user