Skip to content

Commit 46fd704

Browse files
authored
Merge pull request #284 from flimzy/errorDetail
More consistently include the HTTP response code in errors
2 parents 2a7f41f + 7afa7fd commit 46fd704

File tree

4 files changed

+35
-15
lines changed

4 files changed

+35
-15
lines changed

category_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func TestGetCategoryPlaylistsOpt(t *testing.T) {
9292
defer server.Close()
9393

9494
_, err := client.GetCategoryPlaylists(context.Background(), "id", Limit(5), Offset(10))
95-
if want := "Not Found"; err == nil || err.Error() != want {
95+
if want := "spotify: Not Found [404]"; err == nil || err.Error() != want {
9696
t.Errorf("Expected error: want %v, got %v", want, err)
9797
}
9898
}

playlist_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ func TestClient_ReplacePlaylistItems(t *testing.T) {
605605
items: []URI{"spotify:track:track1", "spotify:track:track2"},
606606
},
607607
want: want{
608-
err: "Forbidden",
608+
err: "spotify: Forbidden [403]",
609609
},
610610
},
611611
}
@@ -713,7 +713,7 @@ func TestReorderPlaylistRequest(t *testing.T) {
713713
RangeStart: 3,
714714
InsertBefore: 8,
715715
})
716-
if want := "Not Found"; err == nil || err.Error() != want {
716+
if want := "spotify: Not Found [404]"; err == nil || err.Error() != want {
717717
t.Errorf("Expected error: want %v, got %v", want, err)
718718
}
719719
}

spotify.go

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,13 @@ type Error struct {
154154
}
155155

156156
func (e Error) Error() string {
157-
return e.Message
157+
return fmt.Sprintf("spotify: %s [%d]", e.Message, e.Status)
158+
}
159+
160+
// HTTPStatus returns the HTTP status code returned by the server when the error
161+
// occurred.
162+
func (e Error) HTTPStatus() int {
163+
return e.Status
158164
}
159165

160166
// decodeError decodes an Error from an io.Reader.
@@ -176,7 +182,10 @@ func decodeError(resp *http.Response) error {
176182
}
177183

178184
if len(responseBody) == 0 {
179-
return fmt.Errorf("spotify: HTTP %d: %s (body empty)", resp.StatusCode, http.StatusText(resp.StatusCode))
185+
return Error{
186+
Message: "server response without body",
187+
Status: resp.StatusCode,
188+
}
180189
}
181190

182191
buf := bytes.NewBuffer(responseBody)
@@ -186,18 +195,20 @@ func decodeError(resp *http.Response) error {
186195
}
187196
err = json.NewDecoder(buf).Decode(&e)
188197
if err != nil {
189-
return fmt.Errorf("spotify: couldn't decode error: (%d) [%s]", len(responseBody), responseBody)
198+
return Error{
199+
Message: fmt.Sprintf("failed to decode error response %q", responseBody),
200+
Status: resp.StatusCode,
201+
}
190202
}
191203

204+
e.E.Status = resp.StatusCode
192205
if e.E.Message == "" {
193206
// Some errors will result in there being a useful status-code but an
194-
// empty message, which will confuse the user (who only has access to
195-
// the message and not the code). An example of this is when we send
196-
// some of the arguments directly in the HTTP query and the URL ends-up
197-
// being too long.
207+
// empty message. An example of this is when we send some of the
208+
// arguments directly in the HTTP query and the URL ends-up being too
209+
// long.
198210

199-
e.E.Message = fmt.Sprintf("spotify: unexpected HTTP %d: %s (empty error)",
200-
resp.StatusCode, http.StatusText(resp.StatusCode))
211+
e.E.Message = "server response without error description"
201212
}
202213
if retryAfter, _ := strconv.Atoi(resp.Header.Get("Retry-After")); retryAfter != 0 {
203214
e.E.RetryAfter = time.Now().Add(time.Duration(retryAfter) * time.Second)

spotify_test.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func TestRateLimitExceededReportsRetryAfter(t *testing.T) {
115115
// first attempt fails
116116
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
117117
w.Header().Set("Retry-After", strconv.Itoa(retryAfter))
118-
w.WriteHeader(rateLimitExceededStatusCode)
118+
w.WriteHeader(http.StatusTooManyRequests)
119119
_, _ = io.WriteString(w, `{ "error": { "message": "slow down", "status": 429 } }`)
120120
}),
121121
// next attempt succeeds
@@ -222,7 +222,16 @@ func TestDecode429Error(t *testing.T) {
222222
if err == nil {
223223
t.Fatal("Expected error")
224224
}
225-
if err.Error() != "Too many requests" {
226-
t.Error("Invalid error message:", err.Error())
225+
if err.Error() != "spotify: Too many requests [429]" {
226+
t.Error("Unexpected error message:", err.Error())
227+
}
228+
const wantSTatus = http.StatusTooManyRequests
229+
var gotStatus int
230+
var statusErr interface{ HTTPStatus() int }
231+
if errors.As(err, &statusErr) {
232+
gotStatus = statusErr.HTTPStatus()
233+
}
234+
if gotStatus != wantSTatus {
235+
t.Errorf("Expected status %d, got %d", wantSTatus, gotStatus)
227236
}
228237
}

0 commit comments

Comments
 (0)