// WithOdataErrorUnlessStatusCode returns a RespondDecorator that emits an // azure.RequestError by reading the response body unless the response HTTP status code // is among the set passed. // // If there is a chance service may return responses other than the Azure error // format and the response cannot be parsed into an error, a decoding error will // be returned containing the response body. In any case, the Responder will // return an error if the status code is not satisfied. // // If this Responder returns an error, the response body will be replaced with // an in-memory reader, which needs no further closing. // // NOTE(axw) this function is based on go-autorest/autorest/azure.WithErrorUnlessStatusCode. // The only difference is that we extract "odata.error", instead of "error", // from the response body; and we do not extract the message, which is in a // different format for odata.error, and irrelevant to us. func WithOdataErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { err := r.Respond(resp) if err == nil && !autorest.ResponseHasStatusCode(resp, codes...) { var oe odataRequestError defer resp.Body.Close() // Copy and replace the Body in case it does not contain an error object. // This will leave the Body available to the caller. b, decodeErr := autorest.CopyAndDecode(autorest.EncodedAsJSON, resp.Body, &oe) resp.Body = ioutil.NopCloser(&b) if decodeErr != nil { return fmt.Errorf("ad: error response cannot be parsed: %q error: %v", b.String(), decodeErr) } else if oe.ServiceError == nil { oe.ServiceError = &odataServiceError{Code: "Unknown"} } e := azure.RequestError{ ServiceError: &azure.ServiceError{Code: oe.ServiceError.Code}, RequestID: azure.ExtractRequestID(resp), } if e.StatusCode == nil { e.StatusCode = resp.StatusCode } err = &e } return err }) } }
// WithErrorUnlessStatusCode returns a RespondDecorator that emits an // azure.RequestError by reading the response body unless the response HTTP status code // is among the set passed. // // If there is a chance service may return responses other than the Azure error // format and the response cannot be parsed into an error, a decoding error will // be returned containing the response body. In any case, the Responder will // return an error if the status code is not satisfied. // // If this Responder returns an error, the response body will be replaced with // an in-memory reader, which needs no further closing. func WithErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator { return func(r autorest.Responder) autorest.Responder { return autorest.ResponderFunc(func(resp *http.Response) error { err := r.Respond(resp) if err == nil && !autorest.ResponseHasStatusCode(resp, codes...) { var e RequestError defer resp.Body.Close() b, decodeErr := autorest.CopyAndDecode(autorest.EncodedAsJSON, resp.Body, &e) resp.Body = ioutil.NopCloser(&b) // replace body with in-memory reader if decodeErr != nil || e.ServiceError == nil { return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), err) } e.RequestID = ExtractRequestID(resp) e.StatusCode = resp.StatusCode err = &e } return err }) } }