// Into stores the result into obj, if possible. If obj is nil it is ignored. func (r Result) Into(obj runtime.Object) error { if r.err != nil { return r.err } if r.decoder == nil { return fmt.Errorf("serializer for %s doesn't exist", r.contentType) } return runtime.DecodeInto(r.decoder, r.body, obj) }
// transformResponse converts an API response into a structured API object func (r *Request) transformResponse(resp *http.Response, req *http.Request) Result { var body []byte if resp.Body != nil { if data, err := ioutil.ReadAll(resp.Body); err == nil { body = data } } if glog.V(8) { switch { case bytes.IndexFunc(body, func(r rune) bool { return r < 0x0a }) != -1: glog.Infof("Response Body:\n%s", hex.Dump(body)) default: glog.Infof("Response Body: %s", string(body)) } } // verify the content type is accurate contentType := resp.Header.Get("Content-Type") decoder := r.serializers.Decoder if len(contentType) > 0 && (decoder == nil || (len(r.content.ContentType) > 0 && contentType != r.content.ContentType)) { mediaType, params, err := mime.ParseMediaType(contentType) if err != nil { return Result{err: errors.NewInternalError(err)} } decoder, err = r.serializers.RenegotiatedDecoder(mediaType, params) if err != nil { // if we fail to negotiate a decoder, treat this as an unstructured error switch { case resp.StatusCode == http.StatusSwitchingProtocols: // no-op, we've been upgraded case resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent: return Result{err: r.transformUnstructuredResponseError(resp, req, body)} } return Result{ body: body, contentType: contentType, statusCode: resp.StatusCode, } } } // Did the server give us a status response? isStatusResponse := false status := &unversioned.Status{} // Because release-1.1 server returns Status with empty APIVersion at paths // to the Extensions resources, we need to use DecodeInto here to provide // default groupVersion, otherwise a status response won't be correctly // decoded. err := runtime.DecodeInto(decoder, body, status) if err == nil && len(status.Status) > 0 { isStatusResponse = true } switch { case resp.StatusCode == http.StatusSwitchingProtocols: // no-op, we've been upgraded case resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent: if !isStatusResponse { return Result{err: r.transformUnstructuredResponseError(resp, req, body)} } return Result{err: errors.FromObject(status)} } // If the server gave us a status back, look at what it was. success := resp.StatusCode >= http.StatusOK && resp.StatusCode <= http.StatusPartialContent if isStatusResponse && (status.Status != unversioned.StatusSuccess && !success) { // "Failed" requests are clearly just an error and it makes sense to return them as such. return Result{err: errors.FromObject(status)} } return Result{ body: body, contentType: contentType, statusCode: resp.StatusCode, decoder: decoder, } }