github.com/profzone/eden-framework@v1.0.10/pkg/courier/status_error/status_error.go (about) 1 package status_error 2 3 import ( 4 "bytes" 5 "fmt" 6 "regexp" 7 "sort" 8 "strconv" 9 ) 10 11 // code, key, msg, desc, canBeTalkError 12 var RegexpStatusError = regexp.MustCompile(`@httpError\(([0-9]+),(.+),"(.+)?","(.+)?",(false|true)\);`) 13 14 func NewStatusError(key string, code int64, msg string) *StatusError { 15 return &StatusError{ 16 Key: key, 17 Code: code, 18 Msg: msg, 19 } 20 } 21 22 func ParseString(s string) *StatusError { 23 matched := RegexpStatusError.FindStringSubmatch(s) 24 if len(matched) != 6 { 25 return nil 26 } 27 28 code, _ := strconv.ParseInt(matched[1], 10, 64) 29 canBeTalkErr, _ := strconv.ParseBool(matched[5]) 30 31 return &StatusError{ 32 Code: code, 33 Key: matched[2], 34 Msg: matched[3], 35 Desc: matched[4], 36 CanBeErrorTalk: canBeTalkErr, 37 } 38 } 39 40 func FromError(err error) *StatusError { 41 if err == nil { 42 return nil 43 } 44 45 if statusErrCode, ok := err.(StatusErrorCode); ok { 46 return statusErrCode.StatusError() 47 } 48 49 if statusError, ok := err.(*StatusError); ok { 50 return statusError 51 } 52 53 return UnknownError.StatusError().WithDesc(err.Error()) 54 } 55 56 func (statusErr *StatusError) String() string { 57 return fmt.Sprintf(`@httpError(%d,%s,"%s","%s",%v);`, statusErr.Code, statusErr.Key, statusErr.Msg, statusErr.Desc, statusErr.CanBeErrorTalk) 58 } 59 60 type StatusError struct { 61 // 错误 Key 62 Key string `json:"key" xml:"key"` 63 // 错误代码 64 Code int64 `json:"code" xml:"code"` 65 // 错误信息 66 Msg string `json:"msg" xml:"msg"` 67 // 详细描述 68 Desc string `json:"desc" xml:"desc"` 69 // 是否能作为错误话术 70 CanBeErrorTalk bool `json:"canBeTalkError" xml:"canBeTalkError"` 71 // 错误溯源 72 Source []string `json:"source" xml:"source"` 73 // 请求 ID 74 ID string `json:"id" xml:"id"` 75 // 出错字段 76 ErrorFields ErrorFields `json:"errorFields" xml:"errorFields"` 77 } 78 79 func (statusErr *StatusError) Is(err error) bool { 80 return FromError(statusErr).Code == statusErr.Code 81 } 82 83 func (statusErr *StatusError) Error() string { 84 return fmt.Sprintf("%v[%s][%d][%s%s] %s", statusErr.Source, statusErr.Key, statusErr.Code, statusErr.Msg, statusErr.ErrorFields, statusErr.Desc) 85 } 86 87 func (statusErr *StatusError) Status() int { 88 strCode := fmt.Sprintf("%d", statusErr.Code) 89 if len(strCode) < 3 { 90 return 0 91 } 92 status, _ := strconv.Atoi(strCode[:3]) 93 return status 94 } 95 96 // deprecated 97 func (statusErr *StatusError) HttpCode() int { 98 return statusErr.Status() 99 } 100 101 func (statusErr StatusError) WithErrTalk() *StatusError { 102 statusErr.CanBeErrorTalk = true 103 return &statusErr 104 } 105 106 func (statusErr StatusError) WithMsg(msg string) *StatusError { 107 statusErr.Msg = msg 108 return &statusErr 109 } 110 111 func (statusErr StatusError) WithoutErrTalk() *StatusError { 112 statusErr.CanBeErrorTalk = false 113 return &statusErr 114 } 115 116 func (statusErr StatusError) WithDesc(desc string) *StatusError { 117 statusErr.Desc = desc 118 return &statusErr 119 } 120 121 func (statusErr StatusError) WithID(id string) *StatusError { 122 statusErr.ID = id 123 return &statusErr 124 } 125 126 func (statusErr StatusError) WithSource(sourceName string) *StatusError { 127 length := len(statusErr.Source) 128 if length == 0 || statusErr.Source[length-1] != sourceName { 129 statusErr.Source = append(statusErr.Source, sourceName) 130 } 131 return &statusErr 132 } 133 134 func (statusErr StatusError) WithErrorField(in string, field string, msg string) *StatusError { 135 statusErr.ErrorFields = append(statusErr.ErrorFields, NewErrorField(in, field, msg)) 136 return &statusErr 137 } 138 139 func (statusErr StatusError) WithErrorFields(errorFields ...*ErrorField) *StatusError { 140 statusErr.ErrorFields = append(statusErr.ErrorFields, errorFields...) 141 return &statusErr 142 } 143 144 func NewErrorField(in string, field string, msg string) *ErrorField { 145 return &ErrorField{ 146 In: in, 147 Field: field, 148 Msg: msg, 149 } 150 } 151 152 type ErrorField struct { 153 // 出错字段路径 154 // 这个信息为一个 json 字符串,方便客户端进行定位错误原因 155 // 例如输入中 {"name":{ "alias" : "test"}} 中的alias出错,则返回 "name.alias" 156 // 如果alias是数组, 且第2个元素的a字段错误,则返回"name.alias[2].a" 157 Field string `json:"field" xml:"field"` 158 // 错误信息 159 Msg string `json:"msg" xml:"msg"` 160 // 错误字段位置 161 // body, query, header, path, formData 162 In string `json:"in" xml:"in"` 163 } 164 165 func (s ErrorField) String() string { 166 return "[" + s.In + "]" + s.Field + " " + s.Msg 167 } 168 169 type ErrorFields []*ErrorField 170 171 func (fields ErrorFields) String() string { 172 if len(fields) == 0 { 173 return "" 174 } 175 buf := &bytes.Buffer{} 176 buf.WriteString("<") 177 for _, f := range fields { 178 buf.WriteString(f.String()) 179 } 180 buf.WriteString(">") 181 return buf.String() 182 } 183 184 func (fields ErrorFields) Sort() ErrorFields { 185 sort.Sort(fields) 186 return fields 187 } 188 189 func (fields ErrorFields) Len() int { 190 return len(fields) 191 } 192 func (fields ErrorFields) Swap(i, j int) { 193 fields[i], fields[j] = fields[j], fields[i] 194 } 195 func (fields ErrorFields) Less(i, j int) bool { 196 return fields[i].Field < fields[j].Field 197 }