From 5504e4b3eccb18bbe02c75b5b47272f144488822 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sat, 28 Mar 2020 14:51:49 +0100 Subject: [PATCH] make api errors int; allow for const defaults --- api/error.defaults.go | 66 +++++++++++++++++++++++++++++-------------- api/error.go | 54 ++++++++++++++++++----------------- 2 files changed, 73 insertions(+), 47 deletions(-) diff --git a/api/error.defaults.go b/api/error.defaults.go index 33ff0fa..4a9ee0e 100644 --- a/api/error.defaults.go +++ b/api/error.defaults.go @@ -1,70 +1,94 @@ package api var ( - // ErrorSuccess represents a generic successful service execution - ErrorSuccess = func() Error { return Error{0, "all right", nil} } - - // ErrorFailure is the most generic error - ErrorFailure = func() Error { return Error{1, "it failed", nil} } - // ErrorUnknown represents any error which cause is unknown. // It might also be used for debug purposes as this error // has to be used the less possible - ErrorUnknown = func() Error { return Error{-1, "", nil} } + ErrorUnknown Error = -1 + + // ErrorSuccess represents a generic successful service execution + ErrorSuccess Error = 0 + + // ErrorFailure is the most generic error + ErrorFailure Error = 1 // ErrorNoMatchFound has to be set when trying to fetch data and there is no result - ErrorNoMatchFound = func() Error { return Error{2, "no resource found", nil} } + ErrorNoMatchFound Error = 2 // ErrorAlreadyExists has to be set when trying to insert data, but identifiers or // unique fields already exists - ErrorAlreadyExists = func() Error { return Error{3, "resource already exists", nil} } + ErrorAlreadyExists Error = 3 // ErrorConfig has to be set when there is a configuration error - ErrorConfig = func() Error { return Error{4, "configuration error", nil} } + ErrorConfig Error = 4 // ErrorUpload has to be set when a file upload failed - ErrorUpload = func() Error { return Error{100, "upload failed", nil} } + ErrorUpload Error = 100 // ErrorDownload has to be set when a file download failed - ErrorDownload = func() Error { return Error{101, "download failed", nil} } + ErrorDownload Error = 101 // MissingDownloadHeaders has to be set when the implementation // of a service of type 'download' (which returns a file instead of // a set or output fields) is missing its HEADER field - MissingDownloadHeaders = func() Error { return Error{102, "download headers are missing", nil} } + MissingDownloadHeaders Error = 102 // ErrorMissingDownloadBody has to be set when the implementation // of a service of type 'download' (which returns a file instead of // a set or output fields) is missing its BODY field - ErrorMissingDownloadBody = func() Error { return Error{103, "download body is missing", nil} } + ErrorMissingDownloadBody Error = 103 // ErrorUnknownService is set when there is no service matching // the http request URI. - ErrorUnknownService = func() Error { return Error{200, "unknown service", nil} } + ErrorUnknownService Error = 200 // ErrorUncallableService is set when there the requested service's // implementation (plugin file) is not found/callable - ErrorUncallableService = func() Error { return Error{202, "uncallable service", nil} } + ErrorUncallableService Error = 202 + + // ErrorNotImplemented is set when a handler is not implemented yet + ErrorNotImplemented Error = 203 // ErrorPermission is set when there is a permission error by default // the api returns a permission error when the current scope (built // by middlewares) does not match the scope required in the config. // You can add your own permission policy and use this error - ErrorPermission = func() Error { return Error{300, "permission error", nil} } + ErrorPermission Error = 300 // ErrorToken has to be set (usually in authentication middleware) to tell // the user that this authentication token is expired or invalid - ErrorToken = func() Error { return Error{301, "token error", nil} } + ErrorToken Error = 301 // ErrorMissingParam is set when a *required* parameter is missing from the // http request - ErrorMissingParam = func() Error { return Error{400, "missing parameter", nil} } + ErrorMissingParam Error = 400 // ErrorInvalidParam is set when a given parameter fails its type check as // defined in the config file. - ErrorInvalidParam = func() Error { return Error{401, "invalid parameter", nil} } + ErrorInvalidParam Error = 401 // ErrorInvalidDefaultParam is set when an optional parameter's default value // does not match its type. - ErrorInvalidDefaultParam = func() Error { return Error{402, "invalid default param", nil} } + ErrorInvalidDefaultParam Error = 402 ) + +var errorReasons = map[Error]string{ + ErrorUnknown: "unknown error", + ErrorSuccess: "all right", + ErrorFailure: "it failed", + ErrorNoMatchFound: "resource found", + ErrorAlreadyExists: "already exists", + ErrorConfig: "configuration error", + ErrorUpload: "upload failed", + ErrorDownload: "download failed", + MissingDownloadHeaders: "download headers are missing", + ErrorMissingDownloadBody: "download body is missing", + ErrorUnknownService: "unknown service", + ErrorUncallableService: "uncallable service", + ErrorNotImplemented: "not implemented", + ErrorPermission: "permission error", + ErrorToken: "token error", + ErrorMissingParam: "missing parameter", + ErrorInvalidParam: "invalid parameter", + ErrorInvalidDefaultParam: "invalid default param", +} diff --git a/api/error.go b/api/error.go index 6bee525..ef6c9fd 100644 --- a/api/error.go +++ b/api/error.go @@ -1,40 +1,42 @@ package api import ( + "encoding/json" "fmt" ) // Error represents an http response error following the api format. // These are used by the services to set the *execution status* // directly into the response as JSON alongside response output fields. -type Error struct { - Code int `json:"code"` - Reason string `json:"reason"` - Arguments []interface{} `json:"arguments"` -} +type Error int -// SetArguments set one or multiple arguments to the error -// to be displayed back to API caller -func (e *Error) SetArguments(arg0 interface{}, args ...interface{}) { - - // 1. clear arguments */ - e.Arguments = make([]interface{}, 0) - - // 2. add arg[0] - e.Arguments = append(e.Arguments, arg0) - - // 3. add optional other arguments - for _, arg := range args { - e.Arguments = append(e.Arguments, arg) - } - -} - -// Implements 'error' +// Error implements the error interface func (e Error) Error() string { - if e.Arguments == nil || len(e.Arguments) < 1 { - return fmt.Sprintf("[%d] %s", e.Code, e.Reason) + // use unknown error if no reason + reason, ok := errorReasons[e] + if !ok { + return ErrorUnknown.Error() } - return fmt.Sprintf("[%d] %s (%v)", e.Code, e.Reason, e.Arguments) + return fmt.Sprintf("[%d] %s", e, reason) +} + +// MarshalJSON implements encoding/json.Marshaler interface +func (e Error) MarshalJSON() ([]byte, error) { + // use unknown error if no reason + reason, ok := errorReasons[e] + if !ok { + return ErrorUnknown.MarshalJSON() + } + + // format to proper struct + formatted := struct { + Code int `json:"code"` + Reason string `json:"reason"` + }{ + Code: int(e), + Reason: reason, + } + + return json.Marshal(formatted) }