unmarshal_error.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package s3
  2. import (
  3. "encoding/xml"
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "net/http"
  8. "strings"
  9. "github.com/aws/aws-sdk-go/aws"
  10. "github.com/aws/aws-sdk-go/aws/awserr"
  11. "github.com/aws/aws-sdk-go/aws/request"
  12. )
  13. type xmlErrorResponse struct {
  14. XMLName xml.Name `xml:"Error"`
  15. Code string `xml:"Code"`
  16. Message string `xml:"Message"`
  17. }
  18. func unmarshalError(r *request.Request) {
  19. defer r.HTTPResponse.Body.Close()
  20. defer io.Copy(ioutil.Discard, r.HTTPResponse.Body)
  21. // Bucket exists in a different region, and request needs
  22. // to be made to the correct region.
  23. if r.HTTPResponse.StatusCode == http.StatusMovedPermanently {
  24. r.Error = awserr.NewRequestFailure(
  25. awserr.New("BucketRegionError",
  26. fmt.Sprintf("incorrect region, the bucket is not in '%s' region",
  27. aws.StringValue(r.Config.Region)),
  28. nil),
  29. r.HTTPResponse.StatusCode,
  30. r.RequestID,
  31. )
  32. return
  33. }
  34. var errCode, errMsg string
  35. // Attempt to parse error from body if it is known
  36. resp := &xmlErrorResponse{}
  37. err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp)
  38. if err != nil && err != io.EOF {
  39. errCode = "SerializationError"
  40. errMsg = "failed to decode S3 XML error response"
  41. } else {
  42. errCode = resp.Code
  43. errMsg = resp.Message
  44. }
  45. // Fallback to status code converted to message if still no error code
  46. if len(errCode) == 0 {
  47. statusText := http.StatusText(r.HTTPResponse.StatusCode)
  48. errCode = strings.Replace(statusText, " ", "", -1)
  49. errMsg = statusText
  50. }
  51. r.Error = awserr.NewRequestFailure(
  52. awserr.New(errCode, errMsg, nil),
  53. r.HTTPResponse.StatusCode,
  54. r.RequestID,
  55. )
  56. }