mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-02-24 04:13:16 +00:00
[NOD-398] Change API server type HandlerError to work with errors instead of error strings (#454)
* [NOD-398] Change API server type HandlerError to work with errors instead of error strings * [NOD-398] Rename OriginalError -> Cause and isHandleError -> ok
This commit is contained in:
@@ -13,29 +13,29 @@ import (
|
||||
// a rest route handler or a middleware.
|
||||
type HandlerError struct {
|
||||
Code int
|
||||
Message string
|
||||
Cause error
|
||||
ClientMessage string
|
||||
}
|
||||
|
||||
func (hErr *HandlerError) Error() string {
|
||||
return hErr.Message
|
||||
return hErr.Cause.Error()
|
||||
}
|
||||
|
||||
// NewHandlerError returns a HandlerError with the given code and message.
|
||||
func NewHandlerError(code int, message string) *HandlerError {
|
||||
func NewHandlerError(code int, err error) error {
|
||||
return &HandlerError{
|
||||
Code: code,
|
||||
Message: message,
|
||||
ClientMessage: message,
|
||||
Cause: err,
|
||||
ClientMessage: err.Error(),
|
||||
}
|
||||
}
|
||||
|
||||
// NewHandlerErrorWithCustomClientMessage returns a HandlerError with
|
||||
// the given code, message and client error message.
|
||||
func NewHandlerErrorWithCustomClientMessage(code int, message, clientMessage string) *HandlerError {
|
||||
func NewHandlerErrorWithCustomClientMessage(code int, err error, clientMessage string) error {
|
||||
return &HandlerError{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Cause: err,
|
||||
ClientMessage: clientMessage,
|
||||
}
|
||||
}
|
||||
@@ -43,8 +43,8 @@ func NewHandlerErrorWithCustomClientMessage(code int, message, clientMessage str
|
||||
// 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))
|
||||
func NewInternalServerHandlerError(err error) error {
|
||||
return NewHandlerErrorWithCustomClientMessage(http.StatusInternalServerError, err, http.StatusText(http.StatusInternalServerError))
|
||||
}
|
||||
|
||||
// NewErrorFromDBErrors takes a slice of database errors and a prefix, and
|
||||
@@ -58,13 +58,6 @@ func NewErrorFromDBErrors(prefix string, dbErrors []error) error {
|
||||
return errors.Errorf("%s [%s]", prefix, strings.Join(dbErrorsStrings, ","))
|
||||
}
|
||||
|
||||
// NewHandlerErrorFromDBErrors takes a slice of database errors and a prefix, and
|
||||
// returns an HandlerError with error code http.StatusInternalServerError with
|
||||
// all of the database errors formatted to one string with the given prefix
|
||||
func NewHandlerErrorFromDBErrors(prefix string, dbErrors []error) *HandlerError {
|
||||
return NewInternalServerHandlerError(NewErrorFromDBErrors(prefix, dbErrors).Error())
|
||||
}
|
||||
|
||||
// IsDBRecordNotFoundError returns true if the given dbErrors contains only a RecordNotFound error
|
||||
func IsDBRecordNotFoundError(dbErrors []error) bool {
|
||||
return len(dbErrors) == 1 && gorm.IsRecordNotFoundError(dbErrors[0])
|
||||
@@ -88,9 +81,13 @@ func (err *ClientError) Error() string {
|
||||
|
||||
// SendErr takes a HandlerError and create a ClientError out of it that is sent
|
||||
// to the http client.
|
||||
func SendErr(ctx *ServerContext, w http.ResponseWriter, hErr *HandlerError) {
|
||||
errMsg := fmt.Sprintf("got error: %s", hErr)
|
||||
ctx.Warnf(errMsg)
|
||||
func SendErr(ctx *ServerContext, w http.ResponseWriter, err error) {
|
||||
var hErr *HandlerError
|
||||
var ok bool
|
||||
if hErr, ok = err.(*HandlerError); !ok {
|
||||
hErr = NewInternalServerHandlerError(err).(*HandlerError)
|
||||
}
|
||||
ctx.Warnf("got error: %s", err)
|
||||
w.WriteHeader(hErr.Code)
|
||||
SendJSONResponse(w, &ClientError{
|
||||
ErrorCode: hErr.Code,
|
||||
|
||||
@@ -2,6 +2,7 @@ package httpserverutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"net/http"
|
||||
"runtime/debug"
|
||||
)
|
||||
@@ -38,10 +39,16 @@ func RecoveryMiddleware(h http.Handler) http.Handler {
|
||||
defer func() {
|
||||
recoveryErr := recover()
|
||||
if recoveryErr != nil {
|
||||
var recoveryErrAsError error
|
||||
if rErr, ok := recoveryErr.(error); ok {
|
||||
recoveryErrAsError = rErr
|
||||
} else {
|
||||
recoveryErrAsError = errors.Errorf("%s", recoveryErr)
|
||||
}
|
||||
recoveryErrStr := fmt.Sprintf("%s", recoveryErr)
|
||||
log.Criticalf("Fatal error: %s", recoveryErrStr)
|
||||
log.Criticalf("Fatal error: %+v", recoveryErrStr)
|
||||
log.Criticalf("Stack trace: %s", debug.Stack())
|
||||
SendErr(ctx, w, NewInternalServerHandlerError(recoveryErrStr))
|
||||
SendErr(ctx, w, recoveryErrAsError)
|
||||
}
|
||||
}()
|
||||
h.ServeHTTP(w, r)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package httpserverutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/pkg/errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
// MakeHandler wrapper and gets the relevant request fields
|
||||
// from it.
|
||||
type HandlerFunc func(ctx *ServerContext, r *http.Request, routeParams map[string]string, queryParams map[string]string, requestBody []byte) (
|
||||
interface{}, *HandlerError)
|
||||
interface{}, error)
|
||||
|
||||
// MakeHandler is a wrapper function that takes a handler in the form of HandlerFunc
|
||||
// and returns a function that can be used as a handler in mux.Router.HandleFunc.
|
||||
@@ -24,19 +24,19 @@ func MakeHandler(handler HandlerFunc) func(http.ResponseWriter, *http.Request) {
|
||||
var err error
|
||||
requestBody, err = ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
SendErr(ctx, w, NewInternalServerHandlerError("Error reading POST data"))
|
||||
SendErr(ctx, w, errors.New("Error reading POST data"))
|
||||
}
|
||||
}
|
||||
|
||||
flattenedQueryParams, hErr := flattenQueryParams(r.URL.Query())
|
||||
if hErr != nil {
|
||||
SendErr(ctx, w, hErr)
|
||||
flattenedQueryParams, err := flattenQueryParams(r.URL.Query())
|
||||
if err != nil {
|
||||
SendErr(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
response, hErr := handler(ctx, r, mux.Vars(r), flattenedQueryParams, requestBody)
|
||||
if hErr != nil {
|
||||
SendErr(ctx, w, hErr)
|
||||
response, err := handler(ctx, r, mux.Vars(r), flattenedQueryParams, requestBody)
|
||||
if err != nil {
|
||||
SendErr(ctx, w, err)
|
||||
return
|
||||
}
|
||||
if response != nil {
|
||||
@@ -45,11 +45,11 @@ func MakeHandler(handler HandlerFunc) func(http.ResponseWriter, *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func flattenQueryParams(queryParams map[string][]string) (map[string]string, *HandlerError) {
|
||||
func flattenQueryParams(queryParams map[string][]string) (map[string]string, error) {
|
||||
flattenedMap := make(map[string]string)
|
||||
for param, valuesSlice := range queryParams {
|
||||
if len(valuesSlice) > 1 {
|
||||
return nil, NewHandlerError(http.StatusUnprocessableEntity, fmt.Sprintf("Couldn't parse the '%s' query parameter:"+
|
||||
return nil, NewHandlerError(http.StatusUnprocessableEntity, errors.Errorf("Couldn't parse the '%s' query parameter:"+
|
||||
" expected a single value but got multiple values", param))
|
||||
}
|
||||
flattenedMap[param] = valuesSlice[0]
|
||||
|
||||
Reference in New Issue
Block a user