mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-06 14:16:43 +00:00

* [NOD-398] Change API server type HandlerError to work with errors instead of error strings * [NOD-398] Rename OriginalError -> Cause and isHandleError -> ok
110 lines
3.2 KiB
Go
110 lines
3.2 KiB
Go
package httpserverutils
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/jinzhu/gorm"
|
|
"github.com/pkg/errors"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
// HandlerError is an error returned from
|
|
// a rest route handler or a middleware.
|
|
type HandlerError struct {
|
|
Code int
|
|
Cause error
|
|
ClientMessage string
|
|
}
|
|
|
|
func (hErr *HandlerError) Error() string {
|
|
return hErr.Cause.Error()
|
|
}
|
|
|
|
// NewHandlerError returns a HandlerError with the given code and message.
|
|
func NewHandlerError(code int, err error) error {
|
|
return &HandlerError{
|
|
Code: code,
|
|
Cause: err,
|
|
ClientMessage: err.Error(),
|
|
}
|
|
}
|
|
|
|
// NewHandlerErrorWithCustomClientMessage returns a HandlerError with
|
|
// the given code, message and client error message.
|
|
func NewHandlerErrorWithCustomClientMessage(code int, err error, clientMessage string) error {
|
|
return &HandlerError{
|
|
Code: code,
|
|
Cause: err,
|
|
ClientMessage: clientMessage,
|
|
}
|
|
}
|
|
|
|
// NewInternalServerHandlerError returns a HandlerError with
|
|
// the given message, and the http.StatusInternalServerError
|
|
// status text as client message.
|
|
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
|
|
// returns an error with all of the database errors formatted to one string with
|
|
// the given prefix
|
|
func NewErrorFromDBErrors(prefix string, dbErrors []error) error {
|
|
dbErrorsStrings := make([]string, len(dbErrors))
|
|
for i, dbErr := range dbErrors {
|
|
dbErrorsStrings[i] = fmt.Sprintf("\"%s\"", dbErr)
|
|
}
|
|
return errors.Errorf("%s [%s]", prefix, strings.Join(dbErrorsStrings, ","))
|
|
}
|
|
|
|
// 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])
|
|
}
|
|
|
|
// HasDBError returns true if the given dbErrors contain any errors that aren't RecordNotFound
|
|
func HasDBError(dbErrors []error) bool {
|
|
return !IsDBRecordNotFoundError(dbErrors) && len(dbErrors) > 0
|
|
}
|
|
|
|
// ClientError is the http response that is sent to the
|
|
// client in case of an error.
|
|
type ClientError struct {
|
|
ErrorCode int `json:"errorCode"`
|
|
ErrorMessage string `json:"errorMessage"`
|
|
}
|
|
|
|
func (err *ClientError) Error() string {
|
|
return fmt.Sprintf("%s (Code: %d)", err.ErrorMessage, err.ErrorCode)
|
|
}
|
|
|
|
// 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, 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,
|
|
ErrorMessage: hErr.ClientMessage,
|
|
})
|
|
}
|
|
|
|
// SendJSONResponse encodes the given response to JSON format and
|
|
// sends it to the client
|
|
func SendJSONResponse(w http.ResponseWriter, response interface{}) {
|
|
b, err := json.Marshal(response)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
_, err = fmt.Fprintf(w, string(b))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|