forked from voidint/binding
-
Notifications
You must be signed in to change notification settings - Fork 3
/
errors.go
129 lines (112 loc) · 3.9 KB
/
errors.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
122
123
124
125
126
127
128
129
package binding
import (
"encoding/json"
"net/http"
"strings"
)
// This file shamelessly adapted from martini-contrib/binding
type (
// Errors may be generated during deserialization, binding,
// or validation. It implements the built-in error interface.
Errors []Error
// Error is a powerful implementation of the built-in error
// interface that allows for error classification, custom error
// messages associated with specific fields, or with no
// associations at all.
Error struct {
// An error supports zero or more field names, because an
// error can morph three ways: (1) it can indicate something
// wrong with the request as a whole, (2) it can point to a
// specific problem with a particular input field, or (3) it
// can span multiple related input fields.
FieldNames []string `json:"fieldNames,omitempty"`
// The classification is like an error code, convenient to
// use when processing or categorizing an error programmatically.
// It may also be called the "kind" of error.
Classification string `json:"classification,omitempty"`
// Message should be human-readable and detailed enough to
// pinpoint and resolve the problem, but it should be brief. For
// example, a payload of 100 objects in a JSON array might have
// an error in the 41st object. The message should help the
// end user find and fix the error with their request.
Message string `json:"message,omitempty"`
}
)
// Add adds an error associated with the fields indicated
// by fieldNames, with the given classification and message.
func (e *Errors) Add(fieldNames []string, classification, message string) {
*e = append(*e, Error{
FieldNames: fieldNames,
Classification: classification,
Message: message,
})
}
// Len returns the number of errors.
func (e *Errors) Len() int {
return len(*e)
}
// Has determines whether an Errors slice has an Error with
// a given classification in it; it does not search on messages
// or field names.
func (e *Errors) Has(class string) bool {
for _, err := range *e {
if err.Kind() == class {
return true
}
}
return false
}
// Handle writes the errors to response in JSON form if any errors
// are contained, and it will return true. Otherwise, nothing happens
// and false is returned.
// (The value receiver is due to issue 8: https://github.com/mholt/binding/issues/8)
func (e Errors) Handle(response http.ResponseWriter) bool {
if e.Len() > 0 {
response.Header().Set("Content-Type", jsonContentType)
if e.Has(ContentTypeError) {
response.WriteHeader(http.StatusUnsupportedMediaType)
} else {
response.WriteHeader(http.StatusBadRequest)
}
errOutput, _ := json.Marshal(e)
response.Write(errOutput)
return true
}
return false
}
// ErrorsHandleFunc Errors custom handler
type ErrorsHandleFunc func(e Errors, response http.ResponseWriter) bool
// CustomHandle writes the errors to response by yourself if any errors are contained,
// and it will return true. Otherwise, nothing happens and false is returned.
func (e Errors) CustomHandle(handler ErrorsHandleFunc, response http.ResponseWriter) bool {
return handler(e, response)
}
// Error returns a concatenation of all its error messages.
func (e Errors) Error() string {
messages := make([]string, 0, e.Len())
for _, err := range e {
messages = append(messages, err.Error())
}
return strings.Join(messages, ", ")
}
// Fields returns the list of field names this error is
// associated with.
func (e Error) Fields() []string {
return e.FieldNames
}
// Kind returns this error's classification.
func (e Error) Kind() string {
return e.Classification
}
// Error returns this error's message.
func (e Error) Error() string {
return e.Message
}
const (
RequiredError = "RequiredError"
ContentTypeError = "ContentTypeError"
DeserializationError = "DeserializationError"
TypeError = "TypeError"
BusinessError = "BusinessError"
SystemError = "SystemError"
)