From dbda3f73032c1ea490ec64c11e3fd6b797f617c3 Mon Sep 17 00:00:00 2001 From: deads2k Date: Wed, 8 Apr 2015 11:32:13 -0400 Subject: [PATCH] make .Stream handle error status codes --- pkg/client/request.go | 26 ++++++++++++++++++++++++++ pkg/client/request_test.go | 16 ++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/pkg/client/request.go b/pkg/client/request.go index 7f52805433..87c8852b56 100644 --- a/pkg/client/request.go +++ b/pkg/client/request.go @@ -540,6 +540,8 @@ func isProbableEOF(err error) bool { // Stream formats and executes the request, and offers streaming of the response. // Returns io.ReadCloser which could be used for streaming of the response, or an error +// Any non-2xx http status code causes an error. If we get a non-2xx code, we try to convert the body into an APIStatus object. +// If we can, we return that as an error. Otherwise, we create an error that lists the http status and the content of the response. func (r *Request) Stream() (io.ReadCloser, error) { if r.err != nil { return nil, r.err @@ -556,6 +558,30 @@ func (r *Request) Stream() (io.ReadCloser, error) { if err != nil { return nil, err } + + switch { + case (resp.StatusCode >= 200) && (resp.StatusCode < 300): + return resp.Body, nil + + default: + // we have a decent shot at taking the object returned, parsing it as a status object and returning a more normal error + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("%v while accessing %v", resp.Status, r.finalURL()) + } + + if runtimeObject, err := r.codec.Decode(bodyBytes); err == nil { + statusError := errors.FromObject(runtimeObject) + + if _, ok := statusError.(APIStatus); ok { + return nil, statusError + } + } + + bodyText := string(bodyBytes) + return nil, fmt.Errorf("%s while accessing %v: %s", resp.Status, r.finalURL(), bodyText) + } + return resp.Body, nil } diff --git a/pkg/client/request_test.go b/pkg/client/request_test.go index 9d61e2fb4e..a553f97091 100644 --- a/pkg/client/request_test.go +++ b/pkg/client/request_test.go @@ -531,6 +531,22 @@ func TestRequestStream(t *testing.T) { }, Err: true, }, + { + Request: &Request{ + client: clientFunc(func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusUnauthorized, + Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(testapi.Codec(), &api.Status{ + Status: api.StatusFailure, + Reason: api.StatusReasonUnauthorized, + })))), + }, nil + }), + codec: latest.Codec, + baseURL: &url.URL{}, + }, + Err: true, + }, } for i, testCase := range testCases { body, err := testCase.Request.Stream()