decodedAPIError decodes and returns the error message from the API response. If the message is blank, it returns a fallback message with the status code.
(resp *http.Response)
| 82 | // decodedAPIError decodes and returns the error message from the API response. |
| 83 | // If the message is blank, it returns a fallback message with the status code. |
| 84 | func decodedAPIError(resp *http.Response) error { |
| 85 | // First and foremost, handle Retry-After headers; if set, show this to the user. |
| 86 | if retryAfter := resp.Header.Get("Retry-After"); retryAfter != "" { |
| 87 | // The Retry-After header can be an HTTP Date or delay seconds. |
| 88 | // The date can be used as-is. The delay seconds should have "seconds" appended. |
| 89 | if delay, err := strconv.Atoi(retryAfter); err == nil { |
| 90 | retryAfter = fmt.Sprintf("%d seconds", delay) |
| 91 | } |
| 92 | return fmt.Errorf( |
| 93 | "request failed with status %s; please try again after %s", |
| 94 | resp.Status, |
| 95 | retryAfter, |
| 96 | ) |
| 97 | } |
| 98 | |
| 99 | // Check for JSON data. On non-JSON data, show the status and content type then bail. |
| 100 | // Otherwise, extract the message details from the JSON. |
| 101 | if contentType := resp.Header.Get("Content-Type"); !jsonContentTypeRe.MatchString(contentType) { |
| 102 | return fmt.Errorf( |
| 103 | "expected response with Content-Type \"application/json\" but got status %q with Content-Type %q", |
| 104 | resp.Status, |
| 105 | contentType, |
| 106 | ) |
| 107 | } |
| 108 | var apiError struct { |
| 109 | Error struct { |
| 110 | Type string `json:"type"` |
| 111 | Message string `json:"message"` |
| 112 | PossibleTrackIDs []string `json:"possible_track_ids"` |
| 113 | } `json:"error,omitempty"` |
| 114 | } |
| 115 | if err := json.NewDecoder(resp.Body).Decode(&apiError); err != nil { |
| 116 | return fmt.Errorf("failed to parse API error response: %s", err) |
| 117 | } |
| 118 | if apiError.Error.Message != "" { |
| 119 | if apiError.Error.Type == "track_ambiguous" { |
| 120 | return fmt.Errorf( |
| 121 | "%s: %s", |
| 122 | apiError.Error.Message, |
| 123 | strings.Join(apiError.Error.PossibleTrackIDs, ", "), |
| 124 | ) |
| 125 | } |
| 126 | return errors.New(apiError.Error.Message) |
| 127 | } |
| 128 | return fmt.Errorf("unexpected API response: %d", resp.StatusCode) |
| 129 | } |
no outgoing calls