Skip to content

Commit

Permalink
Merge pull request #78 from versity/ben/cleanup_base
Browse files Browse the repository at this point in the history
Ben/cleanup base
  • Loading branch information
benmcclelland authored Jun 12, 2023
2 parents 115910e + feace16 commit a95d03c
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 75 deletions.
167 changes: 111 additions & 56 deletions s3api/controllers/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func New(be backend.Backend) S3ApiController {

func (c S3ApiController) ListBuckets(ctx *fiber.Ctx) error {
res, err := c.be.ListBuckets()
return Responce(ctx, res, err)
return SendXMLResponse(ctx, res, err)
}

func (c S3ApiController) GetActions(ctx *fiber.Ctx) error {
Expand All @@ -61,30 +61,68 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error {

if uploadId != "" {
if maxParts < 0 || (maxParts == 0 && ctx.Query("max-parts") != "") {
return ErrorResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidMaxParts))
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidMaxParts))
}
if partNumberMarker < 0 || (partNumberMarker == 0 && ctx.Query("part-number-marker") != "") {
return ErrorResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidPartNumberMarker))
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidPartNumberMarker))
}
res, err := c.be.ListObjectParts(bucket, key, uploadId, partNumberMarker, maxParts)
return Responce(ctx, res, err)
return SendXMLResponse(ctx, res, err)
}

if ctx.Request().URI().QueryArgs().Has("acl") {
res, err := c.be.GetObjectAcl(bucket, key)
return Responce(ctx, res, err)
return SendXMLResponse(ctx, res, err)
}

if attrs := ctx.Get("X-Amz-Object-Attributes"); attrs != "" {
res, err := c.be.GetObjectAttributes(bucket, key, strings.Split(attrs, ","))
return Responce(ctx, res, err)
return SendXMLResponse(ctx, res, err)
}

res, err := c.be.GetObject(bucket, key, acceptRange, ctx.Response().BodyWriter())
if err != nil {
return Responce(ctx, res, err)
return SendResponse(ctx, err)
}
return nil
if res == nil {
return SendResponse(ctx, fmt.Errorf("get object nil response"))
}

utils.SetMetaHeaders(ctx, res.Metadata)
var lastmod string
if res.LastModified != nil {
lastmod = res.LastModified.Format(timefmt)
}
utils.SetResponseHeaders(ctx, []utils.CustomHeader{
{
Key: "Content-Length",
Value: fmt.Sprint(res.ContentLength),
},
{
Key: "Content-Type",
Value: getstring(res.ContentType),
},
{
Key: "Content-Encoding",
Value: getstring(res.ContentEncoding),
},
{
Key: "ETag",
Value: getstring(res.ETag),
},
{
Key: "Last-Modified",
Value: lastmod,
},
})
return ctx.SendStatus(http.StatusOK)
}

func getstring(s *string) string {
if s == nil {
return ""
}
return *s
}

func (c S3ApiController) ListActions(ctx *fiber.Ctx) error {
Expand All @@ -96,21 +134,21 @@ func (c S3ApiController) ListActions(ctx *fiber.Ctx) error {

if ctx.Request().URI().QueryArgs().Has("acl") {
res, err := c.be.GetBucketAcl(ctx.Params("bucket"))
return Responce(ctx, res, err)
return SendXMLResponse(ctx, res, err)
}

if ctx.Request().URI().QueryArgs().Has("uploads") {
res, err := c.be.ListMultipartUploads(&s3.ListMultipartUploadsInput{Bucket: aws.String(ctx.Params("bucket"))})
return Responce(ctx, res, err)
return SendXMLResponse(ctx, res, err)
}

if ctx.QueryInt("list-type") == 2 {
res, err := c.be.ListObjectsV2(bucket, prefix, marker, delimiter, maxkeys)
return Responce(ctx, res, err)
return SendXMLResponse(ctx, res, err)
}

res, err := c.be.ListObjects(bucket, prefix, marker, delimiter, maxkeys)
return Responce(ctx, res, err)
return SendXMLResponse(ctx, res, err)
}

func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error {
Expand Down Expand Up @@ -139,11 +177,11 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error {
GrantWriteACP: &grantWriteACP,
})

return Responce[any](ctx, nil, err)
return SendResponse(ctx, err)
}

err := c.be.PutBucket(bucket)
return Responce[any](ctx, nil, err)
return SendResponse(ctx, err)
}

func (c S3ApiController) PutActions(ctx *fiber.Ctx) error {
Expand Down Expand Up @@ -186,20 +224,21 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error {
var err error
contentLength, err = strconv.ParseInt(contentLengthStr, 10, 64)
if err != nil {
return ErrorResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidRequest))
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidRequest))
}
}

if uploadId != "" && partNumberStr != "" {
partNumber := ctx.QueryInt("partNumber", -1)
if partNumber < 1 {
return ErrorResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidPart))
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidPart))
}

body := io.ReadSeeker(bytes.NewReader([]byte(ctx.Body())))
res, err := c.be.PutObjectPart(bucket, keyStart, uploadId,
etag, err := c.be.PutObjectPart(bucket, keyStart, uploadId,
partNumber, contentLength, body)
return Responce(ctx, res, err)
ctx.Response().Header.Set("Etag", etag)
return SendResponse(ctx, err)
}

if grants != "" || acl != "" {
Expand All @@ -217,7 +256,7 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error {
GrantWrite: &granWrite,
GrantWriteACP: &grantWriteACP,
})
return Responce[any](ctx, nil, err)
return SendResponse(ctx, err)
}

if copySource != "" {
Expand All @@ -227,24 +266,25 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error {
srcBucket, srcObject := copySourceSplit[0], copySourceSplit[1:]

res, err := c.be.CopyObject(srcBucket, strings.Join(srcObject, "/"), bucket, keyStart)
return Responce(ctx, res, err)
return SendXMLResponse(ctx, res, err)
}

metadata := utils.GetUserMetaData(&ctx.Request().Header)

res, err := c.be.PutObject(&s3.PutObjectInput{
etag, err := c.be.PutObject(&s3.PutObjectInput{
Bucket: &bucket,
Key: &keyStart,
ContentLength: contentLength,
Metadata: metadata,
Body: bytes.NewReader(ctx.Request().Body()),
})
return Responce(ctx, res, err)
ctx.Response().Header.Set("ETag", etag)
return SendResponse(ctx, err)
}

func (c S3ApiController) DeleteBucket(ctx *fiber.Ctx) error {
err := c.be.DeleteBucket(ctx.Params("bucket"))
return Responce[any](ctx, nil, err)
return SendResponse(ctx, err)
}

func (c S3ApiController) DeleteObjects(ctx *fiber.Ctx) error {
Expand All @@ -254,7 +294,7 @@ func (c S3ApiController) DeleteObjects(ctx *fiber.Ctx) error {
}

err := c.be.DeleteObjects(ctx.Params("bucket"), &s3.DeleteObjectsInput{Delete: &dObj})
return Responce[any](ctx, nil, err)
return SendResponse(ctx, err)
}

func (c S3ApiController) DeleteActions(ctx *fiber.Ctx) error {
Expand All @@ -277,16 +317,17 @@ func (c S3ApiController) DeleteActions(ctx *fiber.Ctx) error {
ExpectedBucketOwner: &expectedBucketOwner,
RequestPayer: types.RequestPayer(requestPayer),
})
return Responce[any](ctx, nil, err)
return SendResponse(ctx, err)
}

err := c.be.DeleteObject(bucket, key)
return Responce[any](ctx, nil, err)
return SendResponse(ctx, err)
}

func (c S3ApiController) HeadBucket(ctx *fiber.Ctx) error {
res, err := c.be.HeadBucket(ctx.Params("bucket"))
return Responce(ctx, res, err)
_, err := c.be.HeadBucket(ctx.Params("bucket"))
// TODO: set bucket response headers
return SendResponse(ctx, err)
}

const (
Expand All @@ -303,37 +344,41 @@ func (c S3ApiController) HeadObject(ctx *fiber.Ctx) error {

res, err := c.be.HeadObject(bucket, key)
if err != nil {
return ErrorResponse(ctx, err)
return SendResponse(ctx, err)
}
if res == nil {
return SendResponse(ctx, fmt.Errorf("head object nil response"))
}

utils.SetMetaHeaders(ctx, res.Metadata)
var lastmod string
if res.LastModified != nil {
lastmod = res.LastModified.Format(timefmt)
}
utils.SetResponseHeaders(ctx, []utils.CustomHeader{
{
Key: "Content-Length",
Value: fmt.Sprint(res.ContentLength),
},
{
Key: "Content-Type",
Value: *res.ContentType,
Value: getstring(res.ContentType),
},
{
Key: "Content-Encoding",
Value: *res.ContentEncoding,
Value: getstring(res.ContentEncoding),
},
{
Key: "ETag",
Value: *res.ETag,
Value: getstring(res.ETag),
},
{
Key: "Last-Modified",
Value: res.LastModified.Format(timefmt),
Value: lastmod,
},
})

// https://github.com/gofiber/fiber/issues/2080
// ctx.SendStatus() sets incorrect content length on HEAD request
ctx.Status(http.StatusOK)
return nil
return SendResponse(ctx, nil)
}

func (c S3ApiController) CreateActions(ctx *fiber.Ctx) error {
Expand All @@ -353,7 +398,7 @@ func (c S3ApiController) CreateActions(ctx *fiber.Ctx) error {
return errors.New("wrong api call")
}
err := c.be.RestoreObject(bucket, key, &restoreRequest)
return Responce[any](ctx, nil, err)
return SendResponse(ctx, err)
}

if uploadId != "" {
Expand All @@ -366,13 +411,30 @@ func (c S3ApiController) CreateActions(ctx *fiber.Ctx) error {
}

res, err := c.be.CompleteMultipartUpload(bucket, key, uploadId, data.Parts)
return Responce(ctx, res, err)
return SendXMLResponse(ctx, res, err)
}
res, err := c.be.CreateMultipartUpload(&s3.CreateMultipartUploadInput{Bucket: &bucket, Key: &key})
return Responce(ctx, res, err)
return SendXMLResponse(ctx, res, err)
}

func Responce[R any](ctx *fiber.Ctx, resp R, err error) error {
func SendResponse(ctx *fiber.Ctx, err error) error {
if err != nil {
serr, ok := err.(s3err.APIError)
if ok {
ctx.Status(serr.HTTPStatusCode)
return ctx.Send(s3err.GetAPIErrorResponse(serr, "", "", ""))
}
return ctx.Send(s3err.GetAPIErrorResponse(
s3err.GetAPIError(s3err.ErrInternalError), "", "", ""))
}

// https://github.com/gofiber/fiber/issues/2080
// ctx.SendStatus() sets incorrect content length on HEAD request
ctx.Status(http.StatusOK)
return nil
}

func SendXMLResponse(ctx *fiber.Ctx, resp any, err error) error {
if err != nil {
serr, ok := err.(s3err.APIError)
if ok {
Expand All @@ -388,23 +450,16 @@ func Responce[R any](ctx *fiber.Ctx, resp R, err error) error {
}

var b []byte
if b, err = xml.Marshal(resp); err != nil {
return err
}

if len(b) > 0 {
ctx.Response().Header.SetContentType(fiber.MIMEApplicationXML)
if resp != nil {
if b, err = xml.Marshal(resp); err != nil {
return err
}

if len(b) > 0 {
ctx.Response().Header.SetContentType(fiber.MIMEApplicationXML)
}
}

return ctx.Send(b)
}

func ErrorResponse(ctx *fiber.Ctx, err error) error {
serr, ok := err.(s3err.APIError)
if ok {
ctx.Status(serr.HTTPStatusCode)
return ctx.Send(s3err.GetAPIErrorResponse(serr, "", "", ""))
}
return ctx.Send(s3err.GetAPIErrorResponse(
s3err.GetAPIError(s3err.ErrInternalError), "", "", ""))
}
Loading

0 comments on commit a95d03c

Please sign in to comment.