errors.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package client
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "net/http"
  8. "github.com/docker/distribution/registry/api/errcode"
  9. "github.com/docker/distribution/registry/api/v2"
  10. )
  11. // UnexpectedHTTPStatusError is returned when an unexpected HTTP status is
  12. // returned when making a registry api call.
  13. type UnexpectedHTTPStatusError struct {
  14. Status string
  15. }
  16. func (e *UnexpectedHTTPStatusError) Error() string {
  17. return fmt.Sprintf("Received unexpected HTTP status: %s", e.Status)
  18. }
  19. // UnexpectedHTTPResponseError is returned when an expected HTTP status code
  20. // is returned, but the content was unexpected and failed to be parsed.
  21. type UnexpectedHTTPResponseError struct {
  22. ParseErr error
  23. Response []byte
  24. }
  25. func (e *UnexpectedHTTPResponseError) Error() string {
  26. return fmt.Sprintf("Error parsing HTTP response: %s: %q", e.ParseErr.Error(), string(e.Response))
  27. }
  28. func parseHTTPErrorResponse(r io.Reader) error {
  29. var errors errcode.Errors
  30. body, err := ioutil.ReadAll(r)
  31. if err != nil {
  32. return err
  33. }
  34. if err := json.Unmarshal(body, &errors); err != nil {
  35. return &UnexpectedHTTPResponseError{
  36. ParseErr: err,
  37. Response: body,
  38. }
  39. }
  40. return errors
  41. }
  42. func handleErrorResponse(resp *http.Response) error {
  43. if resp.StatusCode == 401 {
  44. err := parseHTTPErrorResponse(resp.Body)
  45. if uErr, ok := err.(*UnexpectedHTTPResponseError); ok {
  46. return v2.ErrorCodeUnauthorized.WithDetail(uErr.Response)
  47. }
  48. return err
  49. }
  50. if resp.StatusCode >= 400 && resp.StatusCode < 500 {
  51. return parseHTTPErrorResponse(resp.Body)
  52. }
  53. return &UnexpectedHTTPStatusError{Status: resp.Status}
  54. }
  55. // SuccessStatus returns true if the argument is a successful HTTP response
  56. // code (in the range 200 - 399 inclusive).
  57. func SuccessStatus(status int) bool {
  58. return status >= 200 && status <= 399
  59. }