github.com/aavshr/aws-sdk-go@v1.41.3/aws/awserr/types.go (about)

     1  package awserr
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  )
     7  
     8  // SprintError returns a string of the formatted error code.
     9  //
    10  // Both extra and origErr are optional.  If they are included their lines
    11  // will be added, but if they are not included their lines will be ignored.
    12  func SprintError(code, message, extra string, origErr error) string {
    13  	msg := fmt.Sprintf("%s: %s", code, message)
    14  	if extra != "" {
    15  		msg = fmt.Sprintf("%s\n\t%s", msg, extra)
    16  	}
    17  	if origErr != nil {
    18  		msg = fmt.Sprintf("%s\ncaused by: %s", msg, origErr.Error())
    19  	}
    20  	return msg
    21  }
    22  
    23  // A baseError wraps the code and message which defines an error. It also
    24  // can be used to wrap an original error object.
    25  //
    26  // Should be used as the root for errors satisfying the awserr.Error. Also
    27  // for any error which does not fit into a specific error wrapper type.
    28  type baseError struct {
    29  	// Classification of error
    30  	code string
    31  
    32  	// Detailed information about error
    33  	message string
    34  
    35  	// Optional original error this error is based off of. Allows building
    36  	// chained errors.
    37  	errs []error
    38  }
    39  
    40  // newBaseError returns an error object for the code, message, and errors.
    41  //
    42  // code is a short no whitespace phrase depicting the classification of
    43  // the error that is being created.
    44  //
    45  // message is the free flow string containing detailed information about the
    46  // error.
    47  //
    48  // origErrs is the error objects which will be nested under the new errors to
    49  // be returned.
    50  func newBaseError(code, message string, origErrs []error) *baseError {
    51  	b := &baseError{
    52  		code:    code,
    53  		message: message,
    54  		errs:    origErrs,
    55  	}
    56  
    57  	return b
    58  }
    59  
    60  // Error returns the string representation of the error.
    61  //
    62  // See ErrorWithExtra for formatting.
    63  //
    64  // Satisfies the error interface.
    65  func (b baseError) Error() string {
    66  	size := len(b.errs)
    67  	if size > 0 {
    68  		return SprintError(b.code, b.message, "", errorList(b.errs))
    69  	}
    70  
    71  	return SprintError(b.code, b.message, "", nil)
    72  }
    73  
    74  // String returns the string representation of the error.
    75  // Alias for Error to satisfy the stringer interface.
    76  func (b baseError) String() string {
    77  	return b.Error()
    78  }
    79  
    80  // Code returns the short phrase depicting the classification of the error.
    81  func (b baseError) Code() string {
    82  	return b.code
    83  }
    84  
    85  // Message returns the error details message.
    86  func (b baseError) Message() string {
    87  	return b.message
    88  }
    89  
    90  // OrigErr returns the original error if one was set. Nil is returned if no
    91  // error was set. This only returns the first element in the list. If the full
    92  // list is needed, use BatchedErrors.
    93  func (b baseError) OrigErr() error {
    94  	switch len(b.errs) {
    95  	case 0:
    96  		return nil
    97  	case 1:
    98  		return b.errs[0]
    99  	default:
   100  		if err, ok := b.errs[0].(Error); ok {
   101  			return NewBatchError(err.Code(), err.Message(), b.errs[1:])
   102  		}
   103  		return NewBatchError("BatchedErrors",
   104  			"multiple errors occurred", b.errs)
   105  	}
   106  }
   107  
   108  // OrigErrs returns the original errors if one was set. An empty slice is
   109  // returned if no error was set.
   110  func (b baseError) OrigErrs() []error {
   111  	return b.errs
   112  }
   113  
   114  // So that the Error interface type can be included as an anonymous field
   115  // in the requestError struct and not conflict with the error.Error() method.
   116  type awsError Error
   117  
   118  // A requestError wraps a request or service error.
   119  //
   120  // Composed of baseError for code, message, and original error.
   121  type requestError struct {
   122  	awsError
   123  	statusCode int
   124  	requestID  string
   125  	bytes      []byte
   126  }
   127  
   128  // newRequestError returns a wrapped error with additional information for
   129  // request status code, and service requestID.
   130  //
   131  // Should be used to wrap all request which involve service requests. Even if
   132  // the request failed without a service response, but had an HTTP status code
   133  // that may be meaningful.
   134  //
   135  // Also wraps original errors via the baseError.
   136  func newRequestError(err Error, statusCode int, requestID string) *requestError {
   137  	return &requestError{
   138  		awsError:   err,
   139  		statusCode: statusCode,
   140  		requestID:  requestID,
   141  	}
   142  }
   143  
   144  // Error returns the string representation of the error.
   145  // Satisfies the error interface.
   146  func (r requestError) Error() string {
   147  	extra := fmt.Sprintf("status code: %d, request id: %s",
   148  		r.statusCode, r.requestID)
   149  	return SprintError(r.Code(), r.Message(), extra, r.OrigErr())
   150  }
   151  
   152  // String returns the string representation of the error.
   153  // Alias for Error to satisfy the stringer interface.
   154  func (r requestError) String() string {
   155  	return r.Error()
   156  }
   157  
   158  // StatusCode returns the wrapped status code for the error
   159  func (r requestError) StatusCode() int {
   160  	return r.statusCode
   161  }
   162  
   163  // RequestID returns the wrapped requestID
   164  func (r requestError) RequestID() string {
   165  	return r.requestID
   166  }
   167  
   168  // OrigErrs returns the original errors if one was set. An empty slice is
   169  // returned if no error was set.
   170  func (r requestError) OrigErrs() []error {
   171  	if b, ok := r.awsError.(BatchedErrors); ok {
   172  		return b.OrigErrs()
   173  	}
   174  	return []error{r.OrigErr()}
   175  }
   176  
   177  type unmarshalError struct {
   178  	awsError
   179  	bytes []byte
   180  }
   181  
   182  // Error returns the string representation of the error.
   183  // Satisfies the error interface.
   184  func (e unmarshalError) Error() string {
   185  	extra := hex.Dump(e.bytes)
   186  	return SprintError(e.Code(), e.Message(), extra, e.OrigErr())
   187  }
   188  
   189  // String returns the string representation of the error.
   190  // Alias for Error to satisfy the stringer interface.
   191  func (e unmarshalError) String() string {
   192  	return e.Error()
   193  }
   194  
   195  // Bytes returns the bytes that failed to unmarshal.
   196  func (e unmarshalError) Bytes() []byte {
   197  	return e.bytes
   198  }
   199  
   200  // An error list that satisfies the golang interface
   201  type errorList []error
   202  
   203  // Error returns the string representation of the error.
   204  //
   205  // Satisfies the error interface.
   206  func (e errorList) Error() string {
   207  	msg := ""
   208  	// How do we want to handle the array size being zero
   209  	if size := len(e); size > 0 {
   210  		for i := 0; i < size; i++ {
   211  			msg += e[i].Error()
   212  			// We check the next index to see if it is within the slice.
   213  			// If it is, then we append a newline. We do this, because unit tests
   214  			// could be broken with the additional '\n'
   215  			if i+1 < size {
   216  				msg += "\n"
   217  			}
   218  		}
   219  	}
   220  	return msg
   221  }