github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/registry/client/errors.go (about)

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