diff --git a/staging/src/k8s.io/apimachinery/pkg/util/httpstream/httpstream.go b/staging/src/k8s.io/apimachinery/pkg/util/httpstream/httpstream.go index 9d5fdeeced5..00ce5f785c8 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/httpstream/httpstream.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/httpstream/httpstream.go @@ -114,6 +114,18 @@ func negotiateProtocol(clientProtocols, serverProtocols []string) string { return "" } +func commaSeparatedHeaderValues(header []string) []string { + var parsedClientProtocols []string + for i := range header { + for _, clientProtocol := range strings.Split(header[i], ",") { + if proto := strings.Trim(clientProtocol, " "); len(proto) > 0 { + parsedClientProtocols = append(parsedClientProtocols, proto) + } + } + } + return parsedClientProtocols +} + // Handshake performs a subprotocol negotiation. If the client did request a // subprotocol, Handshake will select the first common value found in // serverProtocols. If a match is found, Handshake adds a response header @@ -121,7 +133,7 @@ func negotiateProtocol(clientProtocols, serverProtocols []string) string { // returned, along with a response header containing the list of protocols the // server can accept. func Handshake(req *http.Request, w http.ResponseWriter, serverProtocols []string) (string, error) { - clientProtocols := req.Header[http.CanonicalHeaderKey(HeaderProtocolVersion)] + clientProtocols := commaSeparatedHeaderValues(req.Header[http.CanonicalHeaderKey(HeaderProtocolVersion)]) if len(clientProtocols) == 0 { return "", fmt.Errorf("unable to upgrade: %s is required", HeaderProtocolVersion) } diff --git a/staging/src/k8s.io/apimachinery/pkg/util/httpstream/httpstream_test.go b/staging/src/k8s.io/apimachinery/pkg/util/httpstream/httpstream_test.go index 2888e8bd9e2..e988bce2b31 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/httpstream/httpstream_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/httpstream/httpstream_test.go @@ -58,11 +58,22 @@ func TestHandshake(t *testing.T) { expectedProtocol: "", expectError: true, }, + "no common protocol with comma separated list": { + clientProtocols: []string{"c, d"}, + serverProtocols: []string{"a", "b"}, + expectedProtocol: "", + expectError: true, + }, "common protocol": { clientProtocols: []string{"b"}, serverProtocols: []string{"a", "b"}, expectedProtocol: "b", }, + "common protocol with comma separated list": { + clientProtocols: []string{"b, c"}, + serverProtocols: []string{"a", "b"}, + expectedProtocol: "b", + }, } for name, test := range tests {