github.com/cloudwego/hertz@v0.9.3/pkg/common/errors/errors.go (about) 1 /* 2 * Copyright 2022 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * The MIT License (MIT) 16 * 17 * Copyright (c) 2014 Manuel MartÃnez-Almeida 18 * 19 * Permission is hereby granted, free of charge, to any person obtaining a copy 20 * of this software and associated documentation files (the "Software"), to deal 21 * in the Software without restriction, including without limitation the rights 22 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 * copies of the Software, and to permit persons to whom the Software is 24 * furnished to do so, subject to the following conditions: 25 * 26 * The above copyright notice and this permission notice shall be included in 27 * all copies or substantial portions of the Software. 28 * 29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 * THE SOFTWARE. 36 * 37 * This file may have been modified by CloudWeGo authors. All CloudWeGo 38 * Modifications are Copyright 2022 CloudWeGo Authors 39 */ 40 41 package errors 42 43 import ( 44 "errors" 45 "fmt" 46 "reflect" 47 "strings" 48 ) 49 50 var ( 51 // These errors are the base error, which are used for checking in errors.Is() 52 ErrNeedMore = errors.New("need more data") 53 ErrChunkedStream = errors.New("chunked stream") 54 ErrBodyTooLarge = errors.New("body size exceeds the given limit") 55 ErrHijacked = errors.New("connection has been hijacked") 56 ErrTimeout = errors.New("timeout") 57 ErrIdleTimeout = errors.New("idle timeout") 58 ErrNothingRead = errors.New("nothing read") 59 ErrShortConnection = errors.New("short connection") 60 ErrNoFreeConns = errors.New("no free connections available to host") 61 ErrConnectionClosed = errors.New("connection closed") 62 ErrNotSupportProtocol = errors.New("not support protocol") 63 ErrNoMultipartForm = errors.New("request has no multipart/form-data Content-Type") 64 ErrBadPoolConn = errors.New("connection is closed by peer while being in the connection pool") 65 ) 66 67 // ErrorType is an unsigned 64-bit error code as defined in the hertz spec. 68 type ErrorType uint64 69 70 type Error struct { 71 Err error 72 Type ErrorType 73 Meta interface{} 74 } 75 76 const ( 77 // ErrorTypeBind is used when Context.Bind() fails. 78 ErrorTypeBind ErrorType = 1 << iota 79 // ErrorTypeRender is used when Context.Render() fails. 80 ErrorTypeRender 81 // ErrorTypePrivate indicates a private error. 82 ErrorTypePrivate 83 // ErrorTypePublic indicates a public error. 84 ErrorTypePublic 85 // ErrorTypeAny indicates any other error. 86 ErrorTypeAny 87 ) 88 89 type ErrorChain []*Error 90 91 var _ error = (*Error)(nil) 92 93 // SetType sets the error's type. 94 func (msg *Error) SetType(flags ErrorType) *Error { 95 msg.Type = flags 96 return msg 97 } 98 99 // AbortWithMsg implements the error interface. 100 func (msg *Error) Error() string { 101 return msg.Err.Error() 102 } 103 104 func (a ErrorChain) String() string { 105 if len(a) == 0 { 106 return "" 107 } 108 var buffer strings.Builder 109 for i, msg := range a { 110 fmt.Fprintf(&buffer, "Error #%02d: %s\n", i+1, msg.Err) 111 if msg.Meta != nil { 112 fmt.Fprintf(&buffer, " Meta: %v\n", msg.Meta) 113 } 114 } 115 return buffer.String() 116 } 117 118 func (msg *Error) Unwrap() error { 119 return msg.Err 120 } 121 122 // SetMeta sets the error's meta data. 123 func (msg *Error) SetMeta(data interface{}) *Error { 124 msg.Meta = data 125 return msg 126 } 127 128 // IsType judges one error. 129 func (msg *Error) IsType(flags ErrorType) bool { 130 return (msg.Type & flags) > 0 131 } 132 133 // JSON creates a properly formatted JSON 134 func (msg *Error) JSON() interface{} { 135 jsonData := make(map[string]interface{}) 136 if msg.Meta != nil { 137 value := reflect.ValueOf(msg.Meta) 138 switch value.Kind() { 139 case reflect.Struct: 140 return msg.Meta 141 case reflect.Map: 142 for _, key := range value.MapKeys() { 143 jsonData[key.String()] = value.MapIndex(key).Interface() 144 } 145 default: 146 jsonData["meta"] = msg.Meta 147 } 148 } 149 if _, ok := jsonData["error"]; !ok { 150 jsonData["error"] = msg.Error() 151 } 152 return jsonData 153 } 154 155 // Errors returns an array will all the error messages. 156 // Example: 157 // 158 // c.Error(errors.New("first")) 159 // c.Error(errors.New("second")) 160 // c.Error(errors.New("third")) 161 // c.Errors.Errors() // == []string{"first", "second", "third"} 162 func (a ErrorChain) Errors() []string { 163 if len(a) == 0 { 164 return nil 165 } 166 errorStrings := make([]string, len(a)) 167 for i, err := range a { 168 errorStrings[i] = err.Error() 169 } 170 return errorStrings 171 } 172 173 // ByType returns a readonly copy filtered the byte. 174 // ie ByType(hertz.ErrorTypePublic) returns a slice of errors with type=ErrorTypePublic. 175 func (a ErrorChain) ByType(typ ErrorType) ErrorChain { 176 if len(a) == 0 { 177 return nil 178 } 179 if typ == ErrorTypeAny { 180 return a 181 } 182 var result ErrorChain 183 for _, msg := range a { 184 if msg.IsType(typ) { 185 result = append(result, msg) 186 } 187 } 188 return result 189 } 190 191 // Last returns the last error in the slice. It returns nil if the array is empty. 192 // Shortcut for errors[len(errors)-1]. 193 func (a ErrorChain) Last() *Error { 194 if length := len(a); length > 0 { 195 return a[length-1] 196 } 197 return nil 198 } 199 200 func (a ErrorChain) JSON() interface{} { 201 switch length := len(a); length { 202 case 0: 203 return nil 204 case 1: 205 return a.Last().JSON() 206 default: 207 jsonData := make([]interface{}, length) 208 for i, err := range a { 209 jsonData[i] = err.JSON() 210 } 211 return jsonData 212 } 213 } 214 215 func New(err error, t ErrorType, meta interface{}) *Error { 216 return &Error{ 217 Err: err, 218 Type: t, 219 Meta: meta, 220 } 221 } 222 223 // shortcut for creating a public *Error from string 224 func NewPublic(err string) *Error { 225 return New(errors.New(err), ErrorTypePublic, nil) 226 } 227 228 func NewPrivate(err string) *Error { 229 return New(errors.New(err), ErrorTypePrivate, nil) 230 } 231 232 func Newf(t ErrorType, meta interface{}, format string, v ...interface{}) *Error { 233 return New(fmt.Errorf(format, v...), t, meta) 234 } 235 236 func NewPublicf(format string, v ...interface{}) *Error { 237 return New(fmt.Errorf(format, v...), ErrorTypePublic, nil) 238 } 239 240 func NewPrivatef(format string, v ...interface{}) *Error { 241 return New(fmt.Errorf(format, v...), ErrorTypePrivate, nil) 242 }