mirror of https://github.com/k3s-io/k3s
Match any Connection header that contains the Upgrade token for websockets
parent
ac8ee45f4f
commit
f2732f18a7
|
@ -20,7 +20,9 @@ import (
|
|||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.google.com/p/go.net/websocket"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
|
@ -52,6 +54,12 @@ func getWatchParams(query url.Values) (label, field labels.Selector, resourceVer
|
|||
return label, field, resourceVersion
|
||||
}
|
||||
|
||||
var connectionUpgradeRegex = regexp.MustCompile("(^|.*,\\s*)upgrade($|\\s*,)")
|
||||
|
||||
func isWebsocketRequest(req *http.Request) bool {
|
||||
return connectionUpgradeRegex.MatchString(strings.ToLower(req.Header.Get("Connection"))) && strings.ToLower(req.Header.Get("Upgrade")) == "websocket"
|
||||
}
|
||||
|
||||
// ServeHTTP processes watch requests.
|
||||
func (h *WatchHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
parts := splitPath(req.URL.Path)
|
||||
|
@ -75,7 +83,7 @@ func (h *WatchHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
// TODO: This is one watch per connection. We want to multiplex, so that
|
||||
// multiple watches of the same thing don't create two watches downstream.
|
||||
watchServer := &WatchServer{watching, h.codec}
|
||||
if req.Header.Get("Connection") == "Upgrade" && req.Header.Get("Upgrade") == "websocket" {
|
||||
if isWebsocketRequest(req) {
|
||||
websocket.Handler(watchServer.HandleWS).ServeHTTP(httplog.Unlogged(w), req)
|
||||
} else {
|
||||
watchServer.ServeHTTP(w, req)
|
||||
|
|
|
@ -200,3 +200,51 @@ func TestWatchParamParsing(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWatchProtocolSelection(t *testing.T) {
|
||||
simpleStorage := &SimpleRESTStorage{}
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": simpleStorage,
|
||||
}, codec, "/prefix/version")
|
||||
server := httptest.NewServer(handler)
|
||||
client := http.Client{}
|
||||
|
||||
dest, _ := url.Parse(server.URL)
|
||||
dest.Path = "/prefix/version/watch/foo"
|
||||
dest.RawQuery = ""
|
||||
|
||||
table := []struct {
|
||||
isWebsocket bool
|
||||
connHeader string
|
||||
}{
|
||||
{true, "Upgrade"},
|
||||
{true, "keep-alive, Upgrade"},
|
||||
{true, "upgrade"},
|
||||
{false, "keep-alive"},
|
||||
}
|
||||
|
||||
for _, item := range table {
|
||||
request, err := http.NewRequest("GET", dest.String(), nil)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
request.Header.Set("Connection", item.connHeader)
|
||||
request.Header.Set("Upgrade", "websocket")
|
||||
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// The requests recognized as websocket requests based on connection
|
||||
// and upgrade headers will not also have the necessary Sec-Websocket-*
|
||||
// headers so it is expected to throw a 400
|
||||
if item.isWebsocket && response.StatusCode != http.StatusBadRequest {
|
||||
t.Errorf("Unexpected response %#v", response)
|
||||
}
|
||||
|
||||
if !item.isWebsocket && response.StatusCode != http.StatusOK {
|
||||
t.Errorf("Unexpected response %#v", response)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue