diff --git a/CHANGELOG.md b/CHANGELOG.md index 13239c3..dec0627 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This document outlines major changes between releases. - Update go version to 1.18 (TrueCloudLab#9) - Update neo-go to v0.101.0 (#8) - Update viper to v1.15.0 (#8) +- Errors have become more detailed (#18) ## [0.26.0] - 2022-12-28 diff --git a/downloader/download.go b/downloader/download.go index f357550..d8f0bc2 100644 --- a/downloader/download.go +++ b/downloader/download.go @@ -225,19 +225,15 @@ func bearerToken(ctx context.Context) *bearer.Token { } func (r *request) handleFrostFSErr(err error, start time.Time) { - r.log.Error( - "could not receive object", + logFields := []zap.Field{ zap.Stringer("elapsed", time.Since(start)), zap.Error(err), - ) - - if client.IsErrObjectNotFound(err) || client.IsErrContainerNotFound(err) { - response.Error(r.RequestCtx, "Not Found", fasthttp.StatusNotFound) - return } + statusCode, msg, additionalFields := response.FormErrorResponse("could not receive object", err) + logFields = append(logFields, additionalFields...) - msg := fmt.Sprintf("could not receive object: %v", err) - response.Error(r.RequestCtx, msg, fasthttp.StatusBadRequest) + r.log.Error("could not receive object", logFields...) + response.Error(r.RequestCtx, msg, statusCode) } // Downloader is a download request handler. diff --git a/response/utils.go b/response/utils.go index 8a7f383..c467d5e 100644 --- a/response/utils.go +++ b/response/utils.go @@ -1,7 +1,41 @@ package response -import "github.com/valyala/fasthttp" +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + sdkstatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + "github.com/valyala/fasthttp" + "go.uber.org/zap" +) func Error(r *fasthttp.RequestCtx, msg string, code int) { r.Error(msg+"\n", code) } + +func FormErrorResponse(message string, err error) (int, string, []zap.Field) { + var ( + msg string + statusCode int + logFields []zap.Field + ) + + st := new(sdkstatus.ObjectAccessDenied) + + switch { + case errors.As(err, &st): + statusCode = fasthttp.StatusForbidden + reason := st.Reason() + msg = fmt.Sprintf("%s: %v: %s", message, err, reason) + logFields = append(logFields, zap.String("error_detail", reason)) + case client.IsErrObjectNotFound(err) || client.IsErrContainerNotFound(err): + statusCode = fasthttp.StatusNotFound + msg = "NotFound" + default: + statusCode = fasthttp.StatusBadRequest + msg = fmt.Sprintf("%s: %v", message, err) + } + + return statusCode, msg, logFields +} diff --git a/uploader/upload.go b/uploader/upload.go index fc904db..d455a13 100644 --- a/uploader/upload.go +++ b/uploader/upload.go @@ -182,8 +182,7 @@ func (u *Uploader) Upload(c *fasthttp.RequestCtx) { } if idObj, err = u.pool.PutObject(u.appCtx, prm); err != nil { - log.Error("could not store file in frostfs", zap.Error(err)) - response.Error(c, "could not store file in frostfs: "+err.Error(), fasthttp.StatusBadRequest) + u.handlePutFrostFSErr(c, err) return } @@ -214,6 +213,14 @@ func (u *Uploader) Upload(c *fasthttp.RequestCtx) { c.Response.Header.SetContentType(jsonHeader) } +func (u *Uploader) handlePutFrostFSErr(r *fasthttp.RequestCtx, err error) { + statusCode, msg, additionalFields := response.FormErrorResponse("could not store file in frostfs", err) + logFields := append([]zap.Field{zap.Error(err)}, additionalFields...) + + u.log.Error("could not store file in frostfs", logFields...) + response.Error(r, msg, statusCode) +} + func (u *Uploader) fetchOwnerAndBearerToken(ctx context.Context) (*user.ID, *bearer.Token) { if tkn, err := tokens.LoadBearerToken(ctx); err == nil && tkn != nil { issuer := bearer.ResolveIssuer(*tkn)