github.com/aliyun/aliyun-oss-go-sdk@v3.0.2+incompatible/oss/error.go (about) 1 package oss 2 3 import ( 4 "encoding/xml" 5 "fmt" 6 "io/ioutil" 7 "net/http" 8 "strconv" 9 "strings" 10 ) 11 12 // ServiceError contains fields of the error response from Oss Service REST API. 13 type ServiceError struct { 14 XMLName xml.Name `xml:"Error"` 15 Code string `xml:"Code"` // The error code returned from OSS to the caller 16 Message string `xml:"Message"` // The detail error message from OSS 17 RequestID string `xml:"RequestId"` // The UUID used to uniquely identify the request 18 HostID string `xml:"HostId"` // The OSS server cluster's Id 19 Endpoint string `xml:"Endpoint"` 20 Ec string `xml:"EC"` 21 RawMessage string // The raw messages from OSS 22 StatusCode int // HTTP status code 23 24 } 25 26 // Error implements interface error 27 func (e ServiceError) Error() string { 28 errorStr := fmt.Sprintf("oss: service returned error: StatusCode=%d, ErrorCode=%s, ErrorMessage=\"%s\", RequestId=%s", e.StatusCode, e.Code, e.Message, e.RequestID) 29 if len(e.Endpoint) > 0 { 30 errorStr = fmt.Sprintf("%s, Endpoint=%s", errorStr, e.Endpoint) 31 } 32 if len(e.Ec) > 0 { 33 errorStr = fmt.Sprintf("%s, Ec=%s", errorStr, e.Ec) 34 } 35 return errorStr 36 } 37 38 // UnexpectedStatusCodeError is returned when a storage service responds with neither an error 39 // nor with an HTTP status code indicating success. 40 type UnexpectedStatusCodeError struct { 41 allowed []int // The expected HTTP stats code returned from OSS 42 got int // The actual HTTP status code from OSS 43 } 44 45 // Error implements interface error 46 func (e UnexpectedStatusCodeError) Error() string { 47 s := func(i int) string { return fmt.Sprintf("%d %s", i, http.StatusText(i)) } 48 49 got := s(e.got) 50 expected := []string{} 51 for _, v := range e.allowed { 52 expected = append(expected, s(v)) 53 } 54 return fmt.Sprintf("oss: status code from service response is %s; was expecting %s", 55 got, strings.Join(expected, " or ")) 56 } 57 58 // Got is the actual status code returned by oss. 59 func (e UnexpectedStatusCodeError) Got() int { 60 return e.got 61 } 62 63 // CheckRespCode returns UnexpectedStatusError if the given response code is not 64 // one of the allowed status codes; otherwise nil. 65 func CheckRespCode(respCode int, allowed []int) error { 66 for _, v := range allowed { 67 if respCode == v { 68 return nil 69 } 70 } 71 return UnexpectedStatusCodeError{allowed, respCode} 72 } 73 74 // CheckCallbackResp return error if the given response code is not 200 75 func CheckCallbackResp(resp *Response) error { 76 var err error 77 contentLengthStr := resp.Headers.Get("Content-Length") 78 contentLength, _ := strconv.Atoi(contentLengthStr) 79 var bodyBytes []byte 80 if contentLength > 0 { 81 bodyBytes, _ = ioutil.ReadAll(resp.Body) 82 } 83 if len(bodyBytes) > 0 { 84 srvErr, errIn := serviceErrFromXML(bodyBytes, resp.StatusCode, 85 resp.Headers.Get(HTTPHeaderOssRequestID)) 86 if errIn != nil { 87 if len(resp.Headers.Get(HTTPHeaderOssEc)) > 0 { 88 err = fmt.Errorf("unknown response body, status code = %d, RequestId = %s, ec = %s", resp.StatusCode, resp.Headers.Get(HTTPHeaderOssRequestID), resp.Headers.Get(HTTPHeaderOssEc)) 89 } else { 90 err = fmt.Errorf("unknown response body, status code= %d, RequestId = %s", resp.StatusCode, resp.Headers.Get(HTTPHeaderOssRequestID)) 91 } 92 } else { 93 err = srvErr 94 } 95 } 96 return err 97 } 98 99 func tryConvertServiceError(data []byte, resp *Response, def error) (err error) { 100 err = def 101 if len(data) > 0 { 102 srvErr, errIn := serviceErrFromXML(data, resp.StatusCode, resp.Headers.Get(HTTPHeaderOssRequestID)) 103 if errIn == nil { 104 err = srvErr 105 } 106 } 107 return err 108 } 109 110 // CRCCheckError is returned when crc check is inconsistent between client and server 111 type CRCCheckError struct { 112 clientCRC uint64 // Calculated CRC64 in client 113 serverCRC uint64 // Calculated CRC64 in server 114 operation string // Upload operations such as PutObject/AppendObject/UploadPart, etc 115 requestID string // The request id of this operation 116 } 117 118 // Error implements interface error 119 func (e CRCCheckError) Error() string { 120 return fmt.Sprintf("oss: the crc of %s is inconsistent, client %d but server %d; request id is %s", 121 e.operation, e.clientCRC, e.serverCRC, e.requestID) 122 } 123 124 func CheckDownloadCRC(clientCRC, serverCRC uint64) error { 125 if clientCRC == serverCRC { 126 return nil 127 } 128 return CRCCheckError{clientCRC, serverCRC, "DownloadFile", ""} 129 } 130 131 func CheckCRC(resp *Response, operation string) error { 132 if resp.Headers.Get(HTTPHeaderOssCRC64) == "" || resp.ClientCRC == resp.ServerCRC { 133 return nil 134 } 135 return CRCCheckError{resp.ClientCRC, resp.ServerCRC, operation, resp.Headers.Get(HTTPHeaderOssRequestID)} 136 }