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

api-error-response.go 4.3 kB

5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package minio_ext
  2. import (
  3. "encoding/xml"
  4. "fmt"
  5. "net/http"
  6. )
  7. type ErrorResponse struct {
  8. XMLName xml.Name `xml:"Error" json:"-"`
  9. Code string
  10. Message string
  11. BucketName string
  12. Key string
  13. RequestID string `xml:"RequestId"`
  14. HostID string `xml:"HostId"`
  15. // Region where the bucket is located. This header is returned
  16. // only in HEAD bucket and ListObjects response.
  17. Region string
  18. // Underlying HTTP status code for the returned error
  19. StatusCode int `xml:"-" json:"-"`
  20. }
  21. // Error - Returns HTTP error string
  22. func (e ErrorResponse) Error() string {
  23. return e.Message
  24. }
  25. const (
  26. reportIssue = "Please report this issue at https://github.com/minio/minio/issues."
  27. )
  28. // httpRespToErrorResponse returns a new encoded ErrorResponse
  29. // structure as error.
  30. func httpRespToErrorResponse(resp *http.Response, bucketName, objectName string) error {
  31. if resp == nil {
  32. msg := "Response is empty. " + reportIssue
  33. return ErrInvalidArgument(msg)
  34. }
  35. errResp := ErrorResponse{
  36. StatusCode: resp.StatusCode,
  37. }
  38. err := xmlDecoder(resp.Body, &errResp)
  39. // Xml decoding failed with no body, fall back to HTTP headers.
  40. if err != nil {
  41. switch resp.StatusCode {
  42. case http.StatusNotFound:
  43. if objectName == "" {
  44. errResp = ErrorResponse{
  45. StatusCode: resp.StatusCode,
  46. Code: "NoSuchBucket",
  47. Message: "The specified bucket does not exist.",
  48. BucketName: bucketName,
  49. }
  50. } else {
  51. errResp = ErrorResponse{
  52. StatusCode: resp.StatusCode,
  53. Code: "NoSuchKey",
  54. Message: "The specified key does not exist.",
  55. BucketName: bucketName,
  56. Key: objectName,
  57. }
  58. }
  59. case http.StatusForbidden:
  60. errResp = ErrorResponse{
  61. StatusCode: resp.StatusCode,
  62. Code: "AccessDenied",
  63. Message: "Access Denied.",
  64. BucketName: bucketName,
  65. Key: objectName,
  66. }
  67. case http.StatusConflict:
  68. errResp = ErrorResponse{
  69. StatusCode: resp.StatusCode,
  70. Code: "Conflict",
  71. Message: "Bucket not empty.",
  72. BucketName: bucketName,
  73. }
  74. case http.StatusPreconditionFailed:
  75. errResp = ErrorResponse{
  76. StatusCode: resp.StatusCode,
  77. Code: "PreconditionFailed",
  78. Message: s3ErrorResponseMap["PreconditionFailed"],
  79. BucketName: bucketName,
  80. Key: objectName,
  81. }
  82. default:
  83. errResp = ErrorResponse{
  84. StatusCode: resp.StatusCode,
  85. Code: resp.Status,
  86. Message: resp.Status,
  87. BucketName: bucketName,
  88. }
  89. }
  90. }
  91. // Save hostID, requestID and region information
  92. // from headers if not available through error XML.
  93. if errResp.RequestID == "" {
  94. errResp.RequestID = resp.Header.Get("x-amz-request-id")
  95. }
  96. if errResp.HostID == "" {
  97. errResp.HostID = resp.Header.Get("x-amz-id-2")
  98. }
  99. if errResp.Region == "" {
  100. errResp.Region = resp.Header.Get("x-amz-bucket-region")
  101. }
  102. if errResp.Code == "InvalidRegion" && errResp.Region != "" {
  103. errResp.Message = fmt.Sprintf("Region does not match, expecting region ‘%s’.", errResp.Region)
  104. }
  105. return errResp
  106. }
  107. func ToErrorResponse(err error) ErrorResponse {
  108. switch err := err.(type) {
  109. case ErrorResponse:
  110. return err
  111. default:
  112. return ErrorResponse{}
  113. }
  114. }
  115. // ErrInvalidArgument - Invalid argument response.
  116. func ErrInvalidArgument(message string) error {
  117. return ErrorResponse{
  118. Code: "InvalidArgument",
  119. Message: message,
  120. RequestID: "minio",
  121. }
  122. }
  123. // ErrEntityTooLarge - Input size is larger than supported maximum.
  124. func ErrEntityTooLarge(totalSize, maxObjectSize int64, bucketName, objectName string) error {
  125. msg := fmt.Sprintf("Your proposed upload size ‘%d’ exceeds the maximum allowed object size ‘%d’ for single PUT operation.", totalSize, maxObjectSize)
  126. return ErrorResponse{
  127. StatusCode: http.StatusBadRequest,
  128. Code: "EntityTooLarge",
  129. Message: msg,
  130. BucketName: bucketName,
  131. Key: objectName,
  132. }
  133. }
  134. // ErrEntityTooSmall - Input size is smaller than supported minimum.
  135. func ErrEntityTooSmall(totalSize int64, bucketName, objectName string) error {
  136. msg := fmt.Sprintf("Your proposed upload size ‘%d’ is below the minimum allowed object size ‘0B’ for single PUT operation.", totalSize)
  137. return ErrorResponse{
  138. StatusCode: http.StatusBadRequest,
  139. Code: "EntityTooSmall",
  140. Message: msg,
  141. BucketName: bucketName,
  142. Key: objectName,
  143. }
  144. }