-
Notifications
You must be signed in to change notification settings - Fork 0
/
rerrors.go
121 lines (105 loc) · 2.83 KB
/
rerrors.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package rerrors
import (
"errors"
"fmt"
"net/http"
)
// package rerrors shares errors accross
// all application layers.
// the name 'rerrors' is to not conflic with golang native errors pkg
// Type holds a type string and integer code for the error
type Type string
// Set of valid errorTypes
const (
BadRequest Type = "BADREQUEST" // Validation errors
Internal Type = "INTERNAL" // Server (500) and fallback errors
NotFound Type = "NOTFOUND" // For not finding resource
Forbidden Type = "FORBIDDEN" // The client has no access rights to the content so the server is refusing to respond
Conflict Type = "CONFLICT" // Already exists - 409
)
// Error holds a custom error for the application
// which is helpful in returning a consistent
// error type/message from API endpoints
type Error struct {
Type Type `json:"type"`
Message string `json:"message"`
}
// Error satisfies standard error interface
// we can return errors from this package as
// a regular old go _error_
func (e *Error) Error() string {
return e.Message
}
// Status is a mapping errors to status codes
// Of course, this is somewhat redundant since
// our errors already map http status codes
func (e *Error) Status() int {
switch e.Type {
case BadRequest:
return http.StatusBadRequest
case Internal:
return http.StatusInternalServerError
case NotFound:
return http.StatusNotFound
case Forbidden:
return http.StatusForbidden
case Conflict:
return http.StatusConflict
default:
return http.StatusInternalServerError
}
}
// Status checks the runtime type
// of the error and returns an http
// status code if the error is model.Error
func Status(err error) int {
var e *Error
if errors.As(err, &e) {
return e.Status()
}
return http.StatusInternalServerError
}
/*
* Error "Factories"
*/
// NewBadRequest to create 400 errors
func NewBadRequest(reason string) *Error {
return &Error{
Type: BadRequest,
Message: fmt.Sprintf("Bad request. Reason: %v", reason),
}
}
// NewInternal for 500 errors
func NewInternal() *Error {
return &Error{
Type: Internal,
Message: "Internal server error.",
}
}
// NewNotFound to create an error for 404
func NewNotFound(name string, value string) *Error {
var message string
if name != "" && value == "" {
message = fmt.Sprintf("resource: %v not found", name)
} else {
message = fmt.Sprintf("resource: %v with value: %v not found", name, value)
}
return &Error{
Type: NotFound,
Message: message,
}
}
// NewForbidden to create 403 errors
func NewForbidden(reason string) *Error {
return &Error{
Type: Forbidden,
Message: fmt.Sprintf("Forbidden. Reason: %v", reason),
}
}
// NewConflict to create 409 erros
func NewConflict(resource, operation, value string) *Error {
return &Error{
Type: Conflict,
Message: fmt.Sprintf("resource: %s not %s: %v", resource, operation, value),
}
}