2015-02-11 01:35:30 +00:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
2015-04-17 20:32:51 +00:00
|
|
|
"encoding/json"
|
2015-02-11 01:35:30 +00:00
|
|
|
"fmt"
|
2015-05-20 02:18:30 +00:00
|
|
|
"io"
|
2015-04-17 20:32:51 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
2015-02-11 01:35:30 +00:00
|
|
|
|
2015-05-15 01:21:39 +00:00
|
|
|
"github.com/docker/distribution/registry/api/errcode"
|
2015-04-17 20:32:51 +00:00
|
|
|
"github.com/docker/distribution/registry/api/v2"
|
2015-02-11 01:35:30 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// UnexpectedHTTPStatusError is returned when an unexpected HTTP status is
|
|
|
|
// returned when making a registry api call.
|
|
|
|
type UnexpectedHTTPStatusError struct {
|
|
|
|
Status string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *UnexpectedHTTPStatusError) Error() string {
|
|
|
|
return fmt.Sprintf("Received unexpected HTTP status: %s", e.Status)
|
|
|
|
}
|
2015-04-17 20:32:51 +00:00
|
|
|
|
|
|
|
// UnexpectedHTTPResponseError is returned when an expected HTTP status code
|
|
|
|
// is returned, but the content was unexpected and failed to be parsed.
|
|
|
|
type UnexpectedHTTPResponseError struct {
|
|
|
|
ParseErr error
|
|
|
|
Response []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *UnexpectedHTTPResponseError) Error() string {
|
2015-05-20 21:55:59 +00:00
|
|
|
return fmt.Sprintf("Error parsing HTTP response: %s: %q", e.ParseErr.Error(), string(e.Response))
|
2015-04-17 20:32:51 +00:00
|
|
|
}
|
|
|
|
|
2015-05-20 02:18:30 +00:00
|
|
|
func parseHTTPErrorResponse(r io.Reader) error {
|
2015-05-15 01:21:39 +00:00
|
|
|
var errors errcode.Errors
|
2015-05-20 02:18:30 +00:00
|
|
|
body, err := ioutil.ReadAll(r)
|
2015-04-17 20:32:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-05-07 23:11:04 +00:00
|
|
|
|
|
|
|
if err := json.Unmarshal(body, &errors); err != nil {
|
2015-04-17 20:32:51 +00:00
|
|
|
return &UnexpectedHTTPResponseError{
|
|
|
|
ParseErr: err,
|
|
|
|
Response: body,
|
|
|
|
}
|
|
|
|
}
|
2015-05-27 00:18:32 +00:00
|
|
|
return errors
|
2015-04-17 20:32:51 +00:00
|
|
|
}
|
2015-05-09 00:40:30 +00:00
|
|
|
|
|
|
|
func handleErrorResponse(resp *http.Response) error {
|
2015-05-20 17:05:44 +00:00
|
|
|
if resp.StatusCode == 401 {
|
|
|
|
err := parseHTTPErrorResponse(resp.Body)
|
|
|
|
if uErr, ok := err.(*UnexpectedHTTPResponseError); ok {
|
2015-06-18 00:39:27 +00:00
|
|
|
return v2.ErrorCodeUnauthorized.WithDetail(uErr.Response)
|
2015-05-20 17:05:44 +00:00
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
2015-05-09 00:40:30 +00:00
|
|
|
if resp.StatusCode >= 400 && resp.StatusCode < 500 {
|
2015-05-20 02:18:30 +00:00
|
|
|
return parseHTTPErrorResponse(resp.Body)
|
2015-05-09 00:40:30 +00:00
|
|
|
}
|
|
|
|
return &UnexpectedHTTPStatusError{Status: resp.Status}
|
|
|
|
}
|
2015-07-24 23:14:04 +00:00
|
|
|
|
|
|
|
// SuccessStatus returns true if the argument is a successful HTTP response
|
|
|
|
// code (in the range 200 - 399 inclusive).
|
|
|
|
func SuccessStatus(status int) bool {
|
|
|
|
return status >= 200 && status <= 399
|
|
|
|
}
|