Skip to content

Commit

Permalink
private/protocol/query: Add parsing of ServiceUnavailableException
Browse files Browse the repository at this point in the history
Adds support to fallback and attempt to parse the
ServiceUnavailableException out of the response body. This is helpful
when the request failed and the service returned unavailable error.
Previously the error unmarshaller would fail with a serialization error.

Fix #331
  • Loading branch information
jasdel committed Mar 16, 2016
1 parent ab0382b commit fdad9d9
Showing 1 changed file with 32 additions and 6 deletions.
38 changes: 32 additions & 6 deletions private/protocol/query/unmarshal_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -15,18 +15,27 @@ 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}

// UnmarshalError unmarshals an error response for an AWS Query service.
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
Expand All @@ -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)
}

0 comments on commit fdad9d9

Please sign in to comment.