-
Notifications
You must be signed in to change notification settings - Fork 0
/
code.go
176 lines (154 loc) · 3.97 KB
/
code.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package e
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"github.com/json-iterator/go"
)
type ErrorCode interface {
error
json.Marshaler
json.Unmarshaler
StatusCode() int
Code() string
Message() string
Result() interface{}
WithStatusCode(int) ErrorCode
WithCode(string) ErrorCode
WithMessage(string) ErrorCode
WithResult(interface{}) ErrorCode
}
type InnerError struct {
Code string `json:"code"`
Message string `json:"message"`
Result interface{} `json:"result"`
}
func From(response *http.Response) ErrorCode {
decoder := jsoniter.ConfigCompatibleWithStandardLibrary.NewDecoder(response.Body)
decoder.UseNumber()
var result ErrCode
if err := decoder.Decode(&result); err != nil {
return ErrParseContent.WithResult(err)
}
return result.WithStatusCode(response.StatusCode)
}
func Froze(code, message string) ErrorCode {
return &ErrCode{
code: code,
msg: message,
}
}
// ErrCode 规定组成部分为http状态码+5位错误码
type ErrCode struct {
code string
msg string
result interface{}
}
func (e *ErrCode) Error() string {
return fmt.Sprintf("code:%s,message:%s,result:%s", e.Code(), e.Message(), e.Result())
}
func (e *ErrCode) MarshalJSON() ([]byte, error) {
inner := &InnerError{
Code: e.code,
Message: e.msg,
Result: e.result,
}
return jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(inner)
}
func (e *ErrCode) UnmarshalJSON(bytes []byte) error {
var result InnerError
if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(bytes, &result); err != nil {
return err
}
e.code = result.Code
e.msg = result.Message
e.result = result.Result
return nil
}
func (e *ErrCode) StatusCode() int {
statusCode, _ := strconv.Atoi(e.code[:3])
return statusCode
}
func (e *ErrCode) Code() string {
return e.code
}
func (e *ErrCode) Message() string {
return e.msg
}
func (e *ErrCode) Result() interface{} {
return e.result
}
func (e *ErrCode) WithStatusCode(statusCode int) ErrorCode {
ec := *e
ec.code = strconv.Itoa(statusCode) + ec.Code()[3:]
return &ec
}
func (e *ErrCode) WithCode(code string) ErrorCode {
ec := *e
ec.code = strconv.Itoa(ec.StatusCode()) + code[3:]
return &ec
}
func (e *ErrCode) WithMessage(msg string) ErrorCode {
ec := *e
ec.msg = msg
return &ec
}
func (e *ErrCode) WithResult(result interface{}) ErrorCode {
ec := *e
ec.result = result
return &ec
}
var (
// 00~99为服务级别错误码
ErrInternalServerError = Froze("5000000000", "服务器内部错误")
ErrInvalidParam = Froze("4000000001", "请求参数不正确")
ErrNotFound = Froze("4040000002", "资源不存在")
ErrNotAllowMethod = Froze("4050000003", "不允许此方法")
ErrParseContent = Froze("5000000004", "解析内容失败")
)
// AddCode business code to codeMessageBox
func AddCode(m map[ErrorCode]struct{}) error {
temp := make(map[string]string)
for errorCode := range map[ErrorCode]struct{}{
ErrInternalServerError: {},
ErrInvalidParam: {},
ErrNotFound: {},
ErrNotAllowMethod: {},
ErrParseContent: {},
} {
if err := validateErrorCode(errorCode); err != nil {
return err
}
code := errorCode.Code()
value, ok := temp[code]
if ok {
return fmt.Errorf("error code %s(%s) already exists", code, value)
}
temp[code] = errorCode.Message()
}
for errorCode := range m {
if err := validateErrorCode(errorCode); err != nil {
return err
}
code := errorCode.Code()
value, ok := temp[code]
if ok {
return fmt.Errorf("error code %s(%s) already exists", code, value)
}
temp[code] = errorCode.Message()
}
return nil
}
// validateErrorCode check err must be 3(http)+3(service)+4(error)
func validateErrorCode(err ErrorCode) error {
code := err.Code()
statusCode := err.StatusCode()
if statusCode < 100 || statusCode >= 600 {
return fmt.Errorf("error code %s has invalid status code %d", code, statusCode)
}
if l := len(code); l != 10 {
return fmt.Errorf("error code %s is %d,but it must be 10", code, l)
}
return nil
}