From 31ccedf1361cecbf9b456f16b7ac6a3f6493ff43 Mon Sep 17 00:00:00 2001 From: Ori Newman Date: Mon, 16 Sep 2019 13:26:05 +0300 Subject: [PATCH] [NOD-325] Enable separate error messages for logging and client (#406) * [NOD-325] Enable separate error messages for logging and client * [NOD-325] Add json annotation to clientError --- apiserver/controllers/block.go | 2 +- apiserver/controllers/transaction.go | 8 +++---- apiserver/server/middlewares.go | 6 ++++-- apiserver/server/routes.go | 12 +++++++++-- apiserver/utils/error.go | 31 +++++++++++++++++++++++----- 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/apiserver/controllers/block.go b/apiserver/controllers/block.go index 01d932e9d..f8862b90d 100644 --- a/apiserver/controllers/block.go +++ b/apiserver/controllers/block.go @@ -20,7 +20,7 @@ func GetBlockByHashHandler(blockHash string) (interface{}, *utils.HandlerError) db, err := database.DB() if err != nil { - return nil, utils.NewHandlerError(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + return nil, utils.NewInternalServerHandlerError(err.Error()) } block := &models.Block{} diff --git a/apiserver/controllers/transaction.go b/apiserver/controllers/transaction.go index e1e262203..064c15964 100644 --- a/apiserver/controllers/transaction.go +++ b/apiserver/controllers/transaction.go @@ -23,7 +23,7 @@ func GetTransactionByIDHandler(txID string) (interface{}, *utils.HandlerError) { db, err := database.DB() if err != nil { - return nil, utils.NewHandlerError(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + return nil, utils.NewInternalServerHandlerError(err.Error()) } tx := &models.Transaction{} @@ -44,7 +44,7 @@ func GetTransactionByHashHandler(txHash string) (interface{}, *utils.HandlerErro db, err := database.DB() if err != nil { - return nil, utils.NewHandlerError(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + return nil, utils.NewInternalServerHandlerError(err.Error()) } tx := &models.Transaction{} @@ -66,7 +66,7 @@ func GetTransactionsByAddressHandler(address string, skip uint64, limit uint64) db, err := database.DB() if err != nil { - return nil, utils.NewHandlerError(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + return nil, utils.NewInternalServerHandlerError(err.Error()) } txs := []*models.Transaction{} @@ -93,7 +93,7 @@ func GetTransactionsByAddressHandler(address string, skip uint64, limit uint64) func GetUTXOsByAddressHandler(address string) (interface{}, *utils.HandlerError) { db, err := database.DB() if err != nil { - return nil, utils.NewHandlerError(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + return nil, utils.NewInternalServerHandlerError(err.Error()) } var transactionOutputs []*models.TransactionOutput diff --git a/apiserver/server/middlewares.go b/apiserver/server/middlewares.go index 7e921cbab..04ceae289 100644 --- a/apiserver/server/middlewares.go +++ b/apiserver/server/middlewares.go @@ -1,6 +1,7 @@ package server import ( + "fmt" "github.com/daglabs/btcd/apiserver/utils" "net/http" "runtime/debug" @@ -31,9 +32,10 @@ func recoveryMiddleware(h http.Handler) http.Handler { defer func() { recoveryErr := recover() if recoveryErr != nil { - log.Criticalf("Fatal error: %s", recoveryErr) + recoveryErrStr := fmt.Sprintf("%s", recoveryErr) + log.Criticalf("Fatal error: %s", recoveryErrStr) log.Criticalf("Stack trace: %s", debug.Stack()) - sendErr(ctx, w, utils.NewHandlerError(http.StatusInternalServerError, "A server error occurred.")) + sendErr(ctx, w, utils.NewInternalServerHandlerError(recoveryErrStr)) } }() h.ServeHTTP(w, r) diff --git a/apiserver/server/routes.go b/apiserver/server/routes.go index c4699a4c9..b577913f3 100644 --- a/apiserver/server/routes.go +++ b/apiserver/server/routes.go @@ -40,11 +40,19 @@ func makeHandler( } } +type clientError struct { + ErrorCode int `json:"errorCode"` + ErrorMessage string `json:"errorMessage"` +} + func sendErr(ctx *utils.APIServerContext, w http.ResponseWriter, hErr *utils.HandlerError) { errMsg := fmt.Sprintf("got error: %s", hErr) ctx.Warnf(errMsg) - w.WriteHeader(hErr.ErrorCode) - sendJSONResponse(w, hErr) + w.WriteHeader(hErr.Code) + sendJSONResponse(w, &clientError{ + ErrorCode: hErr.Code, + ErrorMessage: hErr.ClientMessage, + }) } func sendJSONResponse(w http.ResponseWriter, response interface{}) { diff --git a/apiserver/utils/error.go b/apiserver/utils/error.go index c7c9b10ea..8fa16d04e 100644 --- a/apiserver/utils/error.go +++ b/apiserver/utils/error.go @@ -1,20 +1,41 @@ package utils +import "net/http" + // HandlerError is an error returned from // a rest route handler or a middleware. type HandlerError struct { - ErrorCode int - ErrorMessage string + Code int + Message string + ClientMessage string } func (hErr *HandlerError) Error() string { - return hErr.ErrorMessage + return hErr.Message } // NewHandlerError returns a HandlerError with the given code and message. func NewHandlerError(code int, message string) *HandlerError { return &HandlerError{ - ErrorCode: code, - ErrorMessage: message, + Code: code, + Message: message, + ClientMessage: message, } } + +// NewHandlerErrorWithCustomClientMessage returns a HandlerError with +// the given code, message and client error message. +func NewHandlerErrorWithCustomClientMessage(code int, message, clientMessage string) *HandlerError { + return &HandlerError{ + Code: code, + Message: message, + ClientMessage: clientMessage, + } +} + +// NewInternalServerHandlerError returns a HandlerError with +// the given message, and the http.StatusInternalServerError +// status text as client message. +func NewInternalServerHandlerError(message string) *HandlerError { + return NewHandlerErrorWithCustomClientMessage(http.StatusInternalServerError, message, http.StatusText(http.StatusInternalServerError)) +}