forked from mholt/binding
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patherrors.go
120 lines (105 loc) · 3.5 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
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:"fields,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(DeserializationError) {
response.WriteHeader(http.StatusBadRequest)
} else if e.Has(ContentTypeError) {
response.WriteHeader(http.StatusUnsupportedMediaType)
} else {
response.WriteHeader(StatusUnprocessableEntity)
}
errOutput, _ := json.Marshal(e)
response.Write(errOutput)
return true
}
return false
}
// Error returns a concatenation of all its error messages.
func (e Errors) Error() string {
messages := []string{}
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"
)