You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.3 KiB

  1. package cos
  2. import (
  3. "encoding/json"
  4. "encoding/xml"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "strconv"
  9. "strings"
  10. )
  11. // ErrorResponse 包含 API 返回的错误信息
  12. //
  13. // https://www.qcloud.com/document/product/436/7730
  14. type ErrorResponse struct {
  15. XMLName xml.Name `xml:"Error"`
  16. Response *http.Response `xml:"-"`
  17. Code string
  18. Message string
  19. Resource string
  20. RequestID string `header:"x-cos-request-id,omitempty" url:"-" xml:"RequestId,omitempty"`
  21. TraceID string `xml:"TraceId,omitempty"`
  22. }
  23. // Error returns the error msg
  24. func (r *ErrorResponse) Error() string {
  25. RequestID := r.RequestID
  26. if RequestID == "" {
  27. RequestID = r.Response.Header.Get("X-Cos-Request-Id")
  28. }
  29. TraceID := r.TraceID
  30. if TraceID == "" {
  31. TraceID = r.Response.Header.Get("X-Cos-Trace-Id")
  32. }
  33. decodeURL, err := decodeURIComponent(r.Response.Request.URL.String())
  34. if err != nil {
  35. decodeURL = r.Response.Request.URL.String()
  36. }
  37. return fmt.Sprintf("%v %v: %d %v(Message: %v, RequestId: %v, TraceId: %v)",
  38. r.Response.Request.Method, decodeURL,
  39. r.Response.StatusCode, r.Code, r.Message, RequestID, TraceID)
  40. }
  41. type jsonError struct {
  42. Code int `json:"code,omitempty"`
  43. Message string `json:"message,omitempty"`
  44. RequestID string `json:"request_id,omitempty"`
  45. }
  46. // 检查 response 是否是出错时的返回的 response
  47. func checkResponse(r *http.Response) error {
  48. if c := r.StatusCode; 200 <= c && c <= 299 {
  49. return nil
  50. }
  51. errorResponse := &ErrorResponse{Response: r}
  52. data, err := ioutil.ReadAll(r.Body)
  53. if err == nil && data != nil {
  54. xml.Unmarshal(data, errorResponse)
  55. }
  56. // 是否为 json 格式
  57. if errorResponse.Code == "" {
  58. ctype := strings.TrimLeft(r.Header.Get("Content-Type"), " ")
  59. if strings.HasPrefix(ctype, "application/json") {
  60. var jerror jsonError
  61. json.Unmarshal(data, &jerror)
  62. errorResponse.Code = strconv.Itoa(jerror.Code)
  63. errorResponse.Message = jerror.Message
  64. errorResponse.RequestID = jerror.RequestID
  65. }
  66. }
  67. return errorResponse
  68. }
  69. func IsNotFoundError(e error) bool {
  70. if e == nil {
  71. return false
  72. }
  73. err, ok := e.(*ErrorResponse)
  74. if !ok {
  75. return false
  76. }
  77. if err.Response != nil && err.Response.StatusCode == 404 {
  78. return true
  79. }
  80. return false
  81. }
  82. func IsCOSError(e error) (*ErrorResponse, bool) {
  83. if e == nil {
  84. return nil, false
  85. }
  86. err, ok := e.(*ErrorResponse)
  87. return err, ok
  88. }