error.go raw

   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  }
 207