1package oss 2 3import ( 4 "encoding/xml" 5 "fmt" 6 "net/http" 7 "strings" 8) 9 10// ServiceError contains fields of the error response from Oss Service REST API. 11type ServiceError struct { 12 XMLName xml.Name `xml:"Error"` 13 Code string `xml:"Code"` // The error code returned from OSS to the caller 14 Message string `xml:"Message"` // The detail error message from OSS 15 RequestID string `xml:"RequestId"` // The UUID used to uniquely identify the request 16 HostID string `xml:"HostId"` // The OSS server cluster's Id 17 Endpoint string `xml:"Endpoint"` 18 RawMessage string // The raw messages from OSS 19 StatusCode int // HTTP status code 20} 21 22// Error implements interface error 23func (e ServiceError) Error() string { 24 if e.Endpoint == "" { 25 return fmt.Sprintf("oss: service returned error: StatusCode=%d, ErrorCode=%s, ErrorMessage=\"%s\", RequestId=%s", 26 e.StatusCode, e.Code, e.Message, e.RequestID) 27 } 28 return fmt.Sprintf("oss: service returned error: StatusCode=%d, ErrorCode=%s, ErrorMessage=\"%s\", RequestId=%s, Endpoint=%s", 29 e.StatusCode, e.Code, e.Message, e.RequestID, e.Endpoint) 30} 31 32// UnexpectedStatusCodeError is returned when a storage service responds with neither an error 33// nor with an HTTP status code indicating success. 34type UnexpectedStatusCodeError struct { 35 allowed []int // The expected HTTP stats code returned from OSS 36 got int // The actual HTTP status code from OSS 37} 38 39// Error implements interface error 40func (e UnexpectedStatusCodeError) Error() string { 41 s := func(i int) string { return fmt.Sprintf("%d %s", i, http.StatusText(i)) } 42 43 got := s(e.got) 44 expected := []string{} 45 for _, v := range e.allowed { 46 expected = append(expected, s(v)) 47 } 48 return fmt.Sprintf("oss: status code from service response is %s; was expecting %s", 49 got, strings.Join(expected, " or ")) 50} 51 52// Got is the actual status code returned by oss. 53func (e UnexpectedStatusCodeError) Got() int { 54 return e.got 55} 56 57// checkRespCode returns UnexpectedStatusError if the given response code is not 58// one of the allowed status codes; otherwise nil. 59func checkRespCode(respCode int, allowed []int) error { 60 for _, v := range allowed { 61 if respCode == v { 62 return nil 63 } 64 } 65 return UnexpectedStatusCodeError{allowed, respCode} 66} 67 68// CRCCheckError is returned when crc check is inconsistent between client and server 69type CRCCheckError struct { 70 clientCRC uint64 // Calculated CRC64 in client 71 serverCRC uint64 // Calculated CRC64 in server 72 operation string // Upload operations such as PutObject/AppendObject/UploadPart, etc 73 requestID string // The request id of this operation 74} 75 76// Error implements interface error 77func (e CRCCheckError) Error() string { 78 return fmt.Sprintf("oss: the crc of %s is inconsistent, client %d but server %d; request id is %s", 79 e.operation, e.clientCRC, e.serverCRC, e.requestID) 80} 81 82func checkDownloadCRC(clientCRC, serverCRC uint64) error { 83 if clientCRC == serverCRC { 84 return nil 85 } 86 return CRCCheckError{clientCRC, serverCRC, "DownloadFile", ""} 87} 88 89func checkCRC(resp *Response, operation string) error { 90 if resp.Headers.Get(HTTPHeaderOssCRC64) == "" || resp.ClientCRC == resp.ServerCRC { 91 return nil 92 } 93 return CRCCheckError{resp.ClientCRC, resp.ServerCRC, operation, resp.Headers.Get(HTTPHeaderOssRequestID)} 94} 95