diff --git a/staging/src/k8s.io/apiserver/pkg/registry/generic/rest/proxy.go b/staging/src/k8s.io/apiserver/pkg/registry/generic/rest/proxy.go
index e6ef8cb..dc4eead 100644
--- a/staging/src/k8s.io/apiserver/pkg/registry/generic/rest/proxy.go
+++ b/staging/src/k8s.io/apiserver/pkg/registry/generic/rest/proxy.go
@@ -17,6 +17,8 @@ limitations under the License.
package rest
import (
+ "bufio"
+ "bytes"
"context"
"fmt"
"io"
@@ -77,6 +79,15 @@ func NewUpgradeAwareProxyHandler(location *url.URL, transport http.RoundTripper,
}
}
+func getResponseCode(r io.Reader) (int, []byte, error) {
+ rawResponse := bytes.NewBuffer(make([]byte, 0, 256))
+ resp, err := http.ReadResponse(bufio.NewReader(io.TeeReader(r, rawResponse)), nil)
+ if err != nil {
+ return 0, nil, err
+ }
+ return resp.StatusCode, rawResponse.Bytes(), nil
+}
+
// ServeHTTP handles the proxy request
func (h *UpgradeAwareProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if len(h.Location.Scheme) == 0 {
@@ -156,6 +167,16 @@ func (h *UpgradeAwareProxyHandler) tryUpgrade(w http.ResponseWriter, req *http.R
}
defer backendConn.Close()
+ rawResponseCode, headerBytes, err := getResponseCode(io.MultiReader(bytes.NewReader(rawResponse), backendConn))
+ if err == nil {
+ glog.V(6).Infof("Proxy connection error: %v", err)
+ h.Responder.Error(fmt.Errorf("Proxy connection Error: %T", w))
+ return true
+ }
+
+ if len(headerBytes) > len(rawResponse) {
+ rawResponse = headerBytes
+ }
// Once the connection is hijacked, the ErrorResponder will no longer work, so
// hijacking should be the last step in the upgrade.
requestHijacker, ok := w.(http.Hijacker)
@@ -177,6 +198,15 @@ func (h *UpgradeAwareProxyHandler) tryUpgrade(w http.ResponseWriter, req *http.R
}
}
+ if rawResponseCode != http.StatusSwitchingProtocols {
+ glog.V(6).Infof("Proxy upgrade error, status code %d", rawResponseCode)
+ _, err := io.Copy(requestHijackedConn, backendConn)
+ if err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
+ glog.Errorf("Error proxying data from backend to client: %v", err)
+ }
+ return true
+ }
+
// Proxy the connection.
wg := &sync.WaitGroup{}
wg.Add(2)