11 "github.com/aws/aws-sdk-go/aws"
12 "github.com/aws/aws-sdk-go/aws/awserr"
13 "github.com/aws/aws-sdk-go/aws/request"
14 "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
17 type xmlErrorResponse struct {
18 XMLName xml.Name `xml:"Error"`
19 Code string `xml:"Code"`
20 Message string `xml:"Message"`
23 func unmarshalError(r *request.Request) {
24 defer r.HTTPResponse.Body.Close()
25 defer io.Copy(ioutil.Discard, r.HTTPResponse.Body)
27 // Bucket exists in a different region, and request needs
28 // to be made to the correct region.
29 if r.HTTPResponse.StatusCode == http.StatusMovedPermanently {
31 "incorrect region, the bucket is not in '%s' region at endpoint '%s'",
32 aws.StringValue(r.Config.Region),
33 aws.StringValue(r.Config.Endpoint),
35 if v := r.HTTPResponse.Header.Get("x-amz-bucket-region"); len(v) != 0 {
36 msg += fmt.Sprintf(", bucket is in '%s' region", v)
38 r.Error = awserr.NewRequestFailure(
39 awserr.New("BucketRegionError", msg, nil),
40 r.HTTPResponse.StatusCode,
46 // Attempt to parse error from body if it is known
47 var errResp xmlErrorResponse
48 err := xmlutil.UnmarshalXMLError(&errResp, r.HTTPResponse.Body)
50 // Only capture the error if an unmarshal error occurs that is not EOF,
51 // because S3 might send an error without a error message which causes
52 // the XML unmarshal to fail with EOF.
56 r.Error = awserr.NewRequestFailure(
57 awserr.New(request.ErrCodeSerialization,
58 "failed to unmarshal error message", err),
59 r.HTTPResponse.StatusCode,
65 // Fallback to status code converted to message if still no error code
66 if len(errResp.Code) == 0 {
67 statusText := http.StatusText(r.HTTPResponse.StatusCode)
68 errResp.Code = strings.Replace(statusText, " ", "", -1)
69 errResp.Message = statusText
72 r.Error = awserr.NewRequestFailure(
73 awserr.New(errResp.Code, errResp.Message, err),
74 r.HTTPResponse.StatusCode,
79 // A RequestFailure provides access to the S3 Request ID and Host ID values
80 // returned from API operation errors. Getting the error as a string will
81 // return the formated error with the same information as awserr.RequestFailure,
82 // while also adding the HostID value from the response.
83 type RequestFailure interface {
86 // Host ID is the S3 Host ID needed for debug, and contacting support