diff --git a/s3api/controllers/base.go b/s3api/controllers/base.go index a6138b08..b6da2583 100644 --- a/s3api/controllers/base.go +++ b/s3api/controllers/base.go @@ -18,7 +18,9 @@ import ( "bytes" "encoding/xml" "errors" + "fmt" "io" + "net/http" "strconv" "strings" "time" @@ -314,7 +316,35 @@ func (c S3ApiController) HeadObject(ctx *fiber.Ctx) error { } res, err := c.be.HeadObject(bucket, key) - return Responce(ctx, res, err) + if err != nil { + return ErrorResponse(ctx, err) + } + + utils.SetMetaHeaders(ctx, res.Metadata) + utils.SetResponseHeaders(ctx, []utils.CustomHeader{ + { + Key: "Content-Length", + Value: fmt.Sprint(res.ContentLength), + }, + { + Key: "Content-Type", + Value: *res.ContentType, + }, + { + Key: "Content-Encoding", + Value: *res.ContentEncoding, + }, + { + Key: "ETag", + Value: *res.ETag, + }, + { + Key: "Last-Modified", + Value: res.LastModified.Format("20060102T150405Z"), + }, + }) + + return ctx.SendStatus(http.StatusOK) } func (c S3ApiController) CreateActions(ctx *fiber.Ctx) error { @@ -366,3 +396,13 @@ func Responce[R comparable](ctx *fiber.Ctx, resp R, err error) error { 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), "", "", "")) +} diff --git a/s3api/utils/utils.go b/s3api/utils/utils.go index 05013faf..4d35bbac 100644 --- a/s3api/utils/utils.go +++ b/s3api/utils/utils.go @@ -17,6 +17,7 @@ package utils import ( "bytes" "errors" + "fmt" "net/http" "strings" @@ -62,6 +63,23 @@ func CreateHttpRequestFromCtx(ctx *fiber.Ctx) (*http.Request, error) { return httpReq, nil } +func SetMetaHeaders(ctx *fiber.Ctx, meta map[string]string) { + for key, val := range meta { + ctx.Set(fmt.Sprintf("X-Amz-Meta-%s", key), val) + } +} + +type CustomHeader struct { + Key string + Value string +} + +func SetResponseHeaders(ctx *fiber.Ctx, headers []CustomHeader) { + for _, header := range headers { + ctx.Set(header.Key, header.Value) + } +} + func includeHeader(hdr string) bool { switch { case strings.EqualFold(hdr, "Cache-Control"):