1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package v2error
20
21 import (
22 "encoding/json"
23 "fmt"
24 "net/http"
25 )
26
27 var errors = map[int]string{
28
29 EcodeKeyNotFound: "Key not found",
30 EcodeTestFailed: "Compare failed",
31 EcodeNotFile: "Not a file",
32 ecodeNoMorePeer: "Reached the max number of peers in the cluster",
33 EcodeNotDir: "Not a directory",
34 EcodeNodeExist: "Key already exists",
35 ecodeKeyIsPreserved: "The prefix of given key is a keyword in etcd",
36 EcodeRootROnly: "Root is read only",
37 EcodeDirNotEmpty: "Directory not empty",
38 ecodeExistingPeerAddr: "Peer address has existed",
39 EcodeUnauthorized: "The request requires user authentication",
40
41
42 ecodeValueRequired: "Value is Required in POST form",
43 EcodePrevValueRequired: "PrevValue is Required in POST form",
44 EcodeTTLNaN: "The given TTL in POST form is not a number",
45 EcodeIndexNaN: "The given index in POST form is not a number",
46 ecodeValueOrTTLRequired: "Value or TTL is required in POST form",
47 ecodeTimeoutNaN: "The given timeout in POST form is not a number",
48 ecodeNameRequired: "Name is required in POST form",
49 ecodeIndexOrValueRequired: "Index or value is required",
50 ecodeIndexValueMutex: "Index and value cannot both be specified",
51 EcodeInvalidField: "Invalid field",
52 EcodeInvalidForm: "Invalid POST form",
53 EcodeRefreshValue: "Value provided on refresh",
54 EcodeRefreshTTLRequired: "A TTL must be provided on refresh",
55
56
57 EcodeRaftInternal: "Raft Internal Error",
58 EcodeLeaderElect: "During Leader Election",
59
60
61 EcodeWatcherCleared: "watcher is cleared due to etcd recovery",
62 EcodeEventIndexCleared: "The event in requested index is outdated and cleared",
63 ecodeStandbyInternal: "Standby Internal Error",
64 ecodeInvalidActiveSize: "Invalid active size",
65 ecodeInvalidRemoveDelay: "Standby remove delay",
66
67
68 ecodeClientInternal: "Client Internal Error",
69 }
70
71 var errorStatus = map[int]int{
72 EcodeKeyNotFound: http.StatusNotFound,
73 EcodeNotFile: http.StatusForbidden,
74 EcodeDirNotEmpty: http.StatusForbidden,
75 EcodeUnauthorized: http.StatusUnauthorized,
76 EcodeTestFailed: http.StatusPreconditionFailed,
77 EcodeNodeExist: http.StatusPreconditionFailed,
78 EcodeRaftInternal: http.StatusInternalServerError,
79 EcodeLeaderElect: http.StatusInternalServerError,
80 }
81
82 const (
83 EcodeKeyNotFound = 100
84 EcodeTestFailed = 101
85 EcodeNotFile = 102
86 ecodeNoMorePeer = 103
87 EcodeNotDir = 104
88 EcodeNodeExist = 105
89 ecodeKeyIsPreserved = 106
90 EcodeRootROnly = 107
91 EcodeDirNotEmpty = 108
92 ecodeExistingPeerAddr = 109
93 EcodeUnauthorized = 110
94
95 ecodeValueRequired = 200
96 EcodePrevValueRequired = 201
97 EcodeTTLNaN = 202
98 EcodeIndexNaN = 203
99 ecodeValueOrTTLRequired = 204
100 ecodeTimeoutNaN = 205
101 ecodeNameRequired = 206
102 ecodeIndexOrValueRequired = 207
103 ecodeIndexValueMutex = 208
104 EcodeInvalidField = 209
105 EcodeInvalidForm = 210
106 EcodeRefreshValue = 211
107 EcodeRefreshTTLRequired = 212
108
109 EcodeRaftInternal = 300
110 EcodeLeaderElect = 301
111
112 EcodeWatcherCleared = 400
113 EcodeEventIndexCleared = 401
114 ecodeStandbyInternal = 402
115 ecodeInvalidActiveSize = 403
116 ecodeInvalidRemoveDelay = 404
117
118 ecodeClientInternal = 500
119 )
120
121 type Error struct {
122 ErrorCode int `json:"errorCode"`
123 Message string `json:"message"`
124 Cause string `json:"cause,omitempty"`
125 Index uint64 `json:"index"`
126 }
127
128 func NewRequestError(errorCode int, cause string) *Error {
129 return NewError(errorCode, cause, 0)
130 }
131
132 func NewError(errorCode int, cause string, index uint64) *Error {
133 return &Error{
134 ErrorCode: errorCode,
135 Message: errors[errorCode],
136 Cause: cause,
137 Index: index,
138 }
139 }
140
141
142 func (e Error) Error() string {
143 return e.Message + " (" + e.Cause + ")"
144 }
145
146 func (e Error) toJsonString() string {
147 b, _ := json.Marshal(e)
148 return string(b)
149 }
150
151 func (e Error) StatusCode() int {
152 status, ok := errorStatus[e.ErrorCode]
153 if !ok {
154 status = http.StatusBadRequest
155 }
156 return status
157 }
158
159 func (e Error) WriteTo(w http.ResponseWriter) error {
160 w.Header().Add("X-Etcd-Index", fmt.Sprint(e.Index))
161 w.Header().Set("Content-Type", "application/json")
162 w.WriteHeader(e.StatusCode())
163 _, err := w.Write([]byte(e.toJsonString() + "\n"))
164 return err
165 }
166
View as plain text