github.com/alibabacloud-go/tea@v1.3.10/dara/error.go (about)

     1  package dara
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  	"reflect"
     9  	"strconv"
    10  	"github.com/alibabacloud-go/tea/tea"
    11  )
    12  
    13  type BaseError interface {
    14  	error
    15  	GetName() *string
    16  	GetCode() *string
    17  }
    18  
    19  type ResponseError interface {
    20  	BaseError
    21  	GetRetryAfter() *int64
    22  	GetStatusCode() *int
    23  	GetAccessDeniedDetail() map[string]interface{}
    24  	GetDescription() *string
    25  	GetData() map[string]interface{}
    26  }
    27  
    28  // SDKError struct is used save error code and message
    29  type SDKError struct {
    30  	BaseError
    31  	Code               *string
    32  	Name               *string
    33  	StatusCode         *int
    34  	Message            *string
    35  	Data               *string
    36  	Stack              *string
    37  	errMsg             *string
    38  	Description        *string
    39  	AccessDeniedDetail map[string]interface{}
    40  }
    41  
    42  // CastError is used for cast type fails
    43  type CastError struct {
    44  	Message *string
    45  }
    46  
    47  func TeaSDKError(err error) error {
    48  	if(err == nil) {
    49  		return nil
    50  	}
    51  
    52  	if te, ok := err.(*SDKError); ok {
    53  		return tea.NewSDKError(map[string]interface{}{
    54  			"code": StringValue(te.Code),
    55  			"statusCode": IntValue(te.StatusCode),
    56  			"message": StringValue(te.Message),
    57  			"data": te.Data,
    58  			"description": StringValue(te.Description),
    59  			"accessDeniedDetail": te.AccessDeniedDetail,
    60  		})
    61  	}
    62  
    63  	if respErr, ok := err.(ResponseError); ok { 
    64  		return tea.NewSDKError(map[string]interface{}{
    65  			"code": StringValue(respErr.GetCode()),
    66  			"statusCode": IntValue(respErr.GetStatusCode()),
    67  			"message": respErr.Error(),
    68  			"description": StringValue(respErr.GetDescription()),
    69  			"data": respErr.GetData(),
    70  			"accessDeniedDetail": respErr.GetAccessDeniedDetail(),
    71  		})
    72  	}
    73  
    74  	if baseErr, ok := err.(BaseError); ok { 
    75  		return tea.NewSDKError(map[string]interface{}{
    76  			"code": StringValue(baseErr.GetCode()),
    77  			"message": baseErr.Error(),
    78  		})
    79  	}
    80  
    81  	return err
    82  }
    83  
    84  // NewSDKError is used for shortly create SDKError object
    85  func NewSDKError(obj map[string]interface{}) *SDKError {
    86  	err := &SDKError{}
    87  	err.Name = String("BaseError")
    88  	if val, ok := obj["code"].(int); ok {
    89  		err.Code = String(strconv.Itoa(val))
    90  	} else if val, ok := obj["code"].(string); ok {
    91  		err.Code = String(val)
    92  	}
    93   
    94  	if obj["message"] != nil {
    95  		err.Message = String(obj["message"].(string))
    96  	}
    97  
    98  	if obj["name"] != nil {
    99  
   100  	}
   101  
   102  	if obj["description"] != nil {
   103  		err.Description = String(obj["description"].(string))
   104  	}
   105  	if detail := obj["accessDeniedDetail"]; detail != nil {
   106  		r := reflect.ValueOf(detail)
   107  		if r.Kind().String() == "map" {
   108  			res := make(map[string]interface{})
   109  			tmp := r.MapKeys()
   110  			for _, key := range tmp {
   111  				res[key.String()] = r.MapIndex(key).Interface()
   112  			}
   113  			err.AccessDeniedDetail = res
   114  		}
   115  	}
   116  	if data := obj["data"]; data != nil {
   117  		r := reflect.ValueOf(data)
   118  		if r.Kind().String() == "map" {
   119  			res := make(map[string]interface{})
   120  			tmp := r.MapKeys()
   121  			for _, key := range tmp {
   122  				res[key.String()] = r.MapIndex(key).Interface()
   123  			}
   124  			if statusCode := res["statusCode"]; statusCode != nil {
   125  				if code, ok := statusCode.(int); ok {
   126  					err.StatusCode = Int(code)
   127  				} else if tmp, ok := statusCode.(string); ok {
   128  					code, err_ := strconv.Atoi(tmp)
   129  					if err_ == nil {
   130  						err.StatusCode = Int(code)
   131  					}
   132  				} else if code, ok := statusCode.(*int); ok {
   133  					err.StatusCode = code
   134  				}
   135  			}
   136  		}
   137  		byt := bytes.NewBuffer([]byte{})
   138  		jsonEncoder := json.NewEncoder(byt)
   139  		jsonEncoder.SetEscapeHTML(false)
   140  		jsonEncoder.Encode(data)
   141  		err.Data = String(string(bytes.TrimSpace(byt.Bytes())))
   142  	}
   143  
   144  	if statusCode, ok := obj["statusCode"].(int); ok {
   145  		err.StatusCode = Int(statusCode)
   146  	} else if status, ok := obj["statusCode"].(string); ok {
   147  		statusCode, err_ := strconv.Atoi(status)
   148  		if err_ == nil {
   149  			err.StatusCode = Int(statusCode)
   150  		}
   151  	}
   152  
   153  	return err
   154  }
   155  
   156  func (err *SDKError) ErrorName() *string {
   157  	return err.Name
   158  }
   159  
   160  func (err *SDKError) ErrorMessage() *string {
   161  	return err.Message
   162  }
   163  
   164  func (err *SDKError) GetCode() *string {
   165  	return err.Code
   166  }
   167  
   168  // Set ErrMsg by msg
   169  func (err *SDKError) SetErrMsg(msg string) {
   170  	err.errMsg = String(msg)
   171  }
   172  
   173  func (err *SDKError) Error() string {
   174  	if err.errMsg == nil {
   175  		str := fmt.Sprintf("SDKError:\n   StatusCode: %d\n   Code: %s\n   Message: %s\n   Data: %s\n",
   176  			IntValue(err.StatusCode), StringValue(err.Code), StringValue(err.Message), StringValue(err.Data))
   177  		err.SetErrMsg(str)
   178  	}
   179  	return StringValue(err.errMsg)
   180  }
   181  
   182  // Return message of CastError
   183  func (err *CastError) Error() string {
   184  	return StringValue(err.Message)
   185  }
   186  
   187  func Retryable(err error) *bool {
   188  	if err == nil {
   189  		return Bool(false)
   190  	}
   191  	if realErr, ok := err.(*SDKError); ok {
   192  		if realErr.StatusCode == nil {
   193  			return Bool(false)
   194  		}
   195  		code := IntValue(realErr.StatusCode)
   196  		return Bool(code >= http.StatusInternalServerError)
   197  	}
   198  	return Bool(true)
   199  }
   200  
   201  // NewCastError is used for cast type fails
   202  func NewCastError(message *string) (err error) {
   203  	return &CastError{
   204  		Message: message,
   205  	}
   206  }