go-micro.dev/v5@v5.12.0/errors/errors.go (about)

     1  // Package errors provides a way to return detailed information
     2  // for an RPC request error. The error is normally JSON encoded.
     3  package errors
     4  
     5  import (
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  	"net/http"
    10  )
    11  
    12  //go:generate protoc -I. --go_out=paths=source_relative:. errors.proto
    13  
    14  func (e *Error) Error() string {
    15  	b, _ := json.Marshal(e)
    16  	return string(b)
    17  }
    18  
    19  // New generates a custom error.
    20  func New(id, detail string, code int32) error {
    21  	return &Error{
    22  		Id:     id,
    23  		Code:   code,
    24  		Detail: detail,
    25  		Status: http.StatusText(int(code)),
    26  	}
    27  }
    28  
    29  // Parse tries to parse a JSON string into an error. If that
    30  // fails, it will set the given string as the error detail.
    31  func Parse(err string) *Error {
    32  	e := new(Error)
    33  	errr := json.Unmarshal([]byte(err), e)
    34  	if errr != nil {
    35  		e.Detail = err
    36  	}
    37  	return e
    38  }
    39  
    40  func newError(id string, code int32, detail string, a ...interface{}) error {
    41  	if len(a) > 0 {
    42  		detail = fmt.Sprintf(detail, a...)
    43  	}
    44  	return &Error{
    45  		Id:     id,
    46  		Code:   code,
    47  		Detail: detail,
    48  		Status: http.StatusText(int(code)),
    49  	}
    50  }
    51  
    52  // BadRequest generates a 400 error.
    53  func BadRequest(id, format string, a ...interface{}) error {
    54  	return newError(id, 400, format, a...)
    55  }
    56  
    57  // Unauthorized generates a 401 error.
    58  func Unauthorized(id, format string, a ...interface{}) error {
    59  	return newError(id, 401, format, a...)
    60  }
    61  
    62  // Forbidden generates a 403 error.
    63  func Forbidden(id, format string, a ...interface{}) error {
    64  	return newError(id, 403, format, a...)
    65  }
    66  
    67  // NotFound generates a 404 error.
    68  func NotFound(id, format string, a ...interface{}) error {
    69  	return newError(id, 404, format, a...)
    70  }
    71  
    72  // MethodNotAllowed generates a 405 error.
    73  func MethodNotAllowed(id, format string, a ...interface{}) error {
    74  	return newError(id, 405, format, a...)
    75  }
    76  
    77  // Timeout generates a 408 error.
    78  func Timeout(id, format string, a ...interface{}) error {
    79  	return newError(id, 408, format, a...)
    80  }
    81  
    82  // Conflict generates a 409 error.
    83  func Conflict(id, format string, a ...interface{}) error {
    84  	return newError(id, 409, format, a...)
    85  }
    86  
    87  // InternalServerError generates a 500 error.
    88  func InternalServerError(id, format string, a ...interface{}) error {
    89  	return newError(id, 500, format, a...)
    90  }
    91  
    92  // Equal tries to compare errors.
    93  func Equal(err1 error, err2 error) bool {
    94  	verr1, ok1 := err1.(*Error)
    95  	verr2, ok2 := err2.(*Error)
    96  
    97  	if ok1 != ok2 {
    98  		return false
    99  	}
   100  
   101  	if !ok1 {
   102  		return err1 == err2
   103  	}
   104  
   105  	if verr1.Code != verr2.Code {
   106  		return false
   107  	}
   108  
   109  	return true
   110  }
   111  
   112  // FromError try to convert go error to *Error.
   113  func FromError(err error) *Error {
   114  	if err == nil {
   115  		return nil
   116  	}
   117  	if verr, ok := err.(*Error); ok && verr != nil {
   118  		return verr
   119  	}
   120  
   121  	return Parse(err.Error())
   122  }
   123  
   124  // As finds the first error in err's chain that matches *Error.
   125  func As(err error) (*Error, bool) {
   126  	if err == nil {
   127  		return nil, false
   128  	}
   129  	var merr *Error
   130  	if errors.As(err, &merr) {
   131  		return merr, true
   132  	}
   133  	return nil, false
   134  }
   135  
   136  func NewMultiError() *MultiError {
   137  	return &MultiError{
   138  		Errors: make([]*Error, 0),
   139  	}
   140  }
   141  
   142  func (e *MultiError) Append(err ...*Error) {
   143  	e.Errors = append(e.Errors, err...)
   144  }
   145  
   146  func (e *MultiError) HasErrors() bool {
   147  	return len(e.Errors) > 0
   148  }
   149  
   150  func (e *MultiError) Error() string {
   151  	b, _ := json.Marshal(e)
   152  	return string(b)
   153  }