ReadBodyAsError reads the response as a codersdk.Response, and wraps it in a codersdk.Error type for easy marshaling. This will always return an error, so only call it if the response failed your expectations. Usually via status code checking. nolint:staticcheck
(res *http.Response)
| 410 | // your expectations. Usually via status code checking. |
| 411 | // nolint:staticcheck |
| 412 | func ReadBodyAsError(res *http.Response) error { |
| 413 | if res == nil { |
| 414 | return xerrors.Errorf("no body returned") |
| 415 | } |
| 416 | defer res.Body.Close() |
| 417 | |
| 418 | var requestMethod, requestURL string |
| 419 | if res.Request != nil { |
| 420 | requestMethod = res.Request.Method |
| 421 | if res.Request.URL != nil { |
| 422 | requestURL = res.Request.URL.String() |
| 423 | } |
| 424 | } |
| 425 | |
| 426 | var helpMessage string |
| 427 | if res.StatusCode == http.StatusUnauthorized { |
| 428 | // 401 means the user is not logged in |
| 429 | // 403 would mean that the user is not authorized |
| 430 | helpMessage = "Try logging in using 'coder login'." |
| 431 | } |
| 432 | |
| 433 | resp, err := io.ReadAll(res.Body) |
| 434 | if err != nil { |
| 435 | return xerrors.Errorf("read body: %w", err) |
| 436 | } |
| 437 | |
| 438 | if mimeErr := ExpectJSONMime(res); mimeErr != nil { |
| 439 | if len(resp) > 2048 { |
| 440 | resp = append(resp[:2048], []byte("...")...) |
| 441 | } |
| 442 | if len(resp) == 0 { |
| 443 | resp = []byte("no response body") |
| 444 | } |
| 445 | return &Error{ |
| 446 | statusCode: res.StatusCode, |
| 447 | method: requestMethod, |
| 448 | url: requestURL, |
| 449 | Response: Response{ |
| 450 | Message: mimeErr.Error(), |
| 451 | Detail: string(resp), |
| 452 | }, |
| 453 | Helper: helpMessage, |
| 454 | } |
| 455 | } |
| 456 | |
| 457 | var m Response |
| 458 | err = json.NewDecoder(bytes.NewBuffer(resp)).Decode(&m) |
| 459 | if err != nil { |
| 460 | if errors.Is(err, io.EOF) { |
| 461 | return &Error{ |
| 462 | statusCode: res.StatusCode, |
| 463 | Response: Response{ |
| 464 | Message: "empty response body", |
| 465 | }, |
| 466 | Helper: helpMessage, |
| 467 | } |
| 468 | } |
| 469 | return xerrors.Errorf("decode body: %w", err) |