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  }