diff --git a/private/protocol/query/unmarshal_error.go b/private/protocol/query/unmarshal_error.go index b8e3c7a3125..f2142961717 100644 --- a/private/protocol/query/unmarshal_error.go +++ b/private/protocol/query/unmarshal_error.go @@ -2,7 +2,7 @@ package query import ( "encoding/xml" - "io" + "io/ioutil" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/request" @@ -15,6 +15,10 @@ type xmlErrorResponse struct { RequestID string `xml:"RequestId"` } +type xmlServiceUnavailableResponse struct { + XMLName xml.Name `xml:"ServiceUnavailableException"` +} + // UnmarshalErrorHandler is a name request handler to unmarshal request errors var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.query.UnmarshalError", Fn: UnmarshalError} @@ -22,11 +26,16 @@ var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.query.UnmarshalEr func UnmarshalError(r *request.Request) { defer r.HTTPResponse.Body.Close() - resp := &xmlErrorResponse{} - err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp) - if err != nil && err != io.EOF { - r.Error = awserr.New("SerializationError", "failed to decode query XML error response", err) - } else { + bodyBytes, err := ioutil.ReadAll(r.HTTPResponse.Body) + if err != nil { + r.Error = awserr.New("SerializationError", "failed to read from query HTTP response body", err) + return + } + + // First check for specific error + resp := xmlErrorResponse{} + decodeErr := xml.Unmarshal(bodyBytes, &resp) + if decodeErr == nil { reqID := resp.RequestID if reqID == "" { reqID = r.RequestID @@ -36,5 +45,22 @@ func UnmarshalError(r *request.Request) { r.HTTPResponse.StatusCode, reqID, ) + return + } + + // Check for unhandled error + servUnavailResp := xmlServiceUnavailableResponse{} + unavailErr := xml.Unmarshal(bodyBytes, &servUnavailResp) + if unavailErr == nil { + r.Error = awserr.NewRequestFailure( + awserr.New("ServiceUnavailableException", "service is unavailable", nil), + r.HTTPResponse.StatusCode, + r.RequestID, + ) + return } + + // Failed to retrieve any error message from the response body + r.Error = awserr.New("SerializationError", + "failed to decode query XML error response", decodeErr) }