error.go 3.2 KB

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