func unmarshalHTTPErrorResponse(resp *http.Response) error {
	var body json.RawMessage
	if err := httprequest.UnmarshalJSONResponse(resp, &body); err != nil {
		return errors.Trace(err)
	}
	// genericErrorResponse defines a struct that is compatible with all the
	// known error types, so that we can know which of the
	// possible error types has been returned.
	//
	// Another possible approach might be to look at resp.Request.URL.Path
	// and determine the expected error type from that, but that
	// seems more fragile than this approach.
	type genericErrorResponse struct {
		Error json.RawMessage `json:"error"`
	}
	var generic genericErrorResponse
	if err := json.Unmarshal(body, &generic); err != nil {
		return errors.Annotatef(err, "incompatible error response")
	}
	if bytes.HasPrefix(generic.Error, []byte(`"`)) {
		// The error message is in a string, which means that
		// the error must be in a params.CharmsResponse
		var resp params.CharmsResponse
		if err := json.Unmarshal(body, &resp); err != nil {
			return errors.Annotatef(err, "incompatible error response")
		}
		return &params.Error{
			Message: resp.Error,
			Code:    resp.ErrorCode,
			Info:    resp.ErrorInfo,
		}
	}
	var errorBody []byte
	if len(generic.Error) > 0 {
		// We have an Error field, therefore the error must be in that.
		// (it's a params.ErrorResponse)
		errorBody = generic.Error
	} else {
		// There wasn't an Error field, so the error must be directly
		// in the body of the response.
		errorBody = body
	}
	var perr params.Error
	if err := json.Unmarshal(errorBody, &perr); err != nil {
		return errors.Annotatef(err, "incompatible error response")
	}
	if perr.Message == "" {
		return errors.Errorf("error response with no message")
	}
	return &perr
}
// unmarshalHTTPErrorResponse unmarshals an error response from
// an HTTP endpoint. For historical reasons, these endpoints
// return several different incompatible error response formats.
// We cope with this by accepting all of the possible formats
// and unmarshaling accordingly.
//
// It always returns a non-nil error.
unmarshalHTTPErrorResponse unmarshals an error response from
an HTTP endpoint. For historical reasons, these endpoints
return several different incompatible error response formats.
We cope with this by accepting all of the possible formats
and unmarshaling accordingly.

It always returns a non-nil error.
// unmarshalHTTPErrorResponse unmarshals an error response from // an HTTP endpoint . For historical reasons these endpoints // return several different incompatible error response formats . // We cope with this by accepting all of the possible formats // and unmarshaling accordingly . // // It always returns a non - nil error .
func unmarshalHTTPErrorResponse(resp *http.Response) error {
	var body json.RawMessage
	if err := httprequest.UnmarshalJSONResponse(resp, &body); err != nil {
		return errors.Trace(err)
	}
	 Another possible approach might be to look at resp.Request.URL.Path
	 and determine the expected error type from that, but that
	 seems more fragile than this approach.
	type genericErrorResponse struct {
		Error json.RawMessage `json:"error"`
	}
	var generic genericErrorResponse
	if err := json.Unmarshal(body, &generic); err != nil {
		return errors.Annotatef(err, "incompatible error response")
	}
	if bytes.HasPrefix(generic.Error, []byte(`"`)) {
		 The error message is in a string, which means that
		 the error must be in a params.CharmsResponse
		var resp params.CharmsResponse
		if err := json.Unmarshal(body, &resp); err != nil {
			return errors.Annotatef(err, "incompatible error response")
		}
		return &params.Error{
			Message: resp.Error,
			Code:    resp.ErrorCode,
			Info:    resp.ErrorInfo,
		}
	}
	var errorBody []byte
	if len(generic.Error) > 0 {
		 We have an Error field, therefore the error must be in that.
		 (it's a params.ErrorResponse)
		errorBody = generic.Error
	} else {
		 There wasn't an Error field, so the error must be directly
		 in the body of the response.
		errorBody = body
	}
	var perr params.Error
	if err := json.Unmarshal(errorBody, &perr); err != nil {
		return errors.Annotatef(err, "incompatible error response")
	}
	if perr.Message == "" {
		return errors.Errorf("error response with no message")
	}
	return &perr
}
func unmarshalHTTPErrorResponse ( resp * http . Response ) error { var body json . RawMessage if err := httprequest . UnmarshalJSONResponse ( resp , & body ) ; err != nil { return errors . Trace ( err ) } type genericErrorResponse struct { Error json . RawMessage `json:"error"` } var generic genericErrorResponse if err := json . Unmarshal ( body , & generic ) ; err != nil { return errors . Annotatef ( err , " " ) } if bytes . HasPrefix ( generic . Error , [ ] byte ( `"` ) ) { var resp params . CharmsResponse if err := json . Unmarshal ( body , & resp ) ; err != nil { return errors . Annotatef ( err , " " ) } return & params . Error { Message : resp . Error , Code : resp . ErrorCode , Info : resp . ErrorInfo , } } var errorBody [ ] byte if len ( generic . Error ) > 0 { errorBody = generic . Error } else { errorBody = body } var perr params . Error if err := json . Unmarshal ( errorBody , & perr ) ; err != nil { return errors . Annotatef ( err , " " ) } if perr . Message == " " { return errors . Errorf ( " " ) } return & perr }
unmarshalHTTPErrorResponse unmarshals an error response from
an HTTP endpoint.
unmarshalHTTPErrorResponse unmarshals an error response from an HTTP endpoint .
// genericErrorResponse defines a struct that is compatible with all the // known error types, so that we can know which of the // possible error types has been returned. // // Another possible approach might be to look at resp.Request.URL.Path // and determine the expected error type from that, but that // seems more fragile than this approach. // The error message is in a string, which means that // the error must be in a params.CharmsResponse // We have an Error field, therefore the error must be in that. // (it's a params.ErrorResponse) // There wasn't an Error field, so the error must be directly // in the body of the response.