make api errors int; allow for const defaults

This commit is contained in:
Adrien Marquès 2020-03-28 14:51:49 +01:00
parent 2f9534a3b0
commit 5504e4b3ec
Signed by: xdrm-brackets
GPG Key ID: D75243CA236D825E
2 changed files with 73 additions and 47 deletions

View File

@ -1,70 +1,94 @@
package api package api
var ( 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. // ErrorUnknown represents any error which cause is unknown.
// It might also be used for debug purposes as this error // It might also be used for debug purposes as this error
// has to be used the less possible // 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 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 // ErrorAlreadyExists has to be set when trying to insert data, but identifiers or
// unique fields already exists // 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 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 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 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 // MissingDownloadHeaders has to be set when the implementation
// of a service of type 'download' (which returns a file instead of // of a service of type 'download' (which returns a file instead of
// a set or output fields) is missing its HEADER field // 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 // ErrorMissingDownloadBody has to be set when the implementation
// of a service of type 'download' (which returns a file instead of // of a service of type 'download' (which returns a file instead of
// a set or output fields) is missing its BODY field // 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 // ErrorUnknownService is set when there is no service matching
// the http request URI. // 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 // ErrorUncallableService is set when there the requested service's
// implementation (plugin file) is not found/callable // 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 // ErrorPermission is set when there is a permission error by default
// the api returns a permission error when the current scope (built // the api returns a permission error when the current scope (built
// by middlewares) does not match the scope required in the config. // by middlewares) does not match the scope required in the config.
// You can add your own permission policy and use this error // 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 // ErrorToken has to be set (usually in authentication middleware) to tell
// the user that this authentication token is expired or invalid // 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 // ErrorMissingParam is set when a *required* parameter is missing from the
// http request // 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 // ErrorInvalidParam is set when a given parameter fails its type check as
// defined in the config file. // 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 // ErrorInvalidDefaultParam is set when an optional parameter's default value
// does not match its type. // 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",
}

View File

@ -1,40 +1,42 @@
package api package api
import ( import (
"encoding/json"
"fmt" "fmt"
) )
// Error represents an http response error following the api format. // Error represents an http response error following the api format.
// These are used by the services to set the *execution status* // These are used by the services to set the *execution status*
// directly into the response as JSON alongside response output fields. // directly into the response as JSON alongside response output fields.
type Error struct { type Error int
Code int `json:"code"`
Reason string `json:"reason"`
Arguments []interface{} `json:"arguments"`
}
// SetArguments set one or multiple arguments to the error // Error implements the error interface
// 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'
func (e Error) Error() string { func (e Error) Error() string {
if e.Arguments == nil || len(e.Arguments) < 1 { // use unknown error if no reason
return fmt.Sprintf("[%d] %s", e.Code, e.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)
} }