From f077fc13d9bd48bd940d882a8b0fba0b8ba88b5e Mon Sep 17 00:00:00 2001 From: urihoenig Date: Mon, 16 Dec 2019 13:27:48 +0200 Subject: [PATCH] IG-12673: Use golang proxy for websocket instead of koding/websocketproxy (#20) --- README.md | 3 +- go.mod | 2 - go.sum | 4 - .../numofrequests/metricshandler.go | 44 +---- pkg/util/util.go | 166 ------------------ pkg/util/websocket.go | 43 ----- 6 files changed, 8 insertions(+), 254 deletions(-) delete mode 100644 pkg/util/util.go delete mode 100644 pkg/util/websocket.go diff --git a/README.md b/README.md index f61d6e5..9e24792 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ facilitate scale-to-zero flows. Supported metrics: 1. General: - * `num_of_requests` - prometheus `CounterVec` that simply counts requests using a reverse proxy. Supports both HTTP - (Go's built in ReverseProxy) and Websocket (https://github.com/koding/websocketproxy) requests
+ * `num_of_requests` - prometheus `CounterVec` that simply counts requests using a reverse proxy (Go's built in ReverseProxy)
2. Service specific: * Jupyter: * `jupyter_kernel_busyness` - prometheus `GaugeVec` that is set to 1 if Jupyter has one or more busy kernels, diff --git a/go.mod b/go.mod index e34b391..5ae7e7a 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,6 @@ go 1.13 require ( github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf // indirect - github.com/gorilla/websocket v1.4.1 - github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c github.com/nuclio/errors v0.0.1 github.com/nuclio/logger v0.0.1 github.com/nuclio/loggerus v0.0.1 diff --git a/go.sum b/go.sum index c935a94..06e6fcb 100644 --- a/go.sum +++ b/go.sum @@ -31,13 +31,9 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg= github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= -github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c h1:N7A4JCA2G+j5fuFxCsJqjFU/sZe0mj8H0sSoSwbaikw= -github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c/go.mod h1:Nn5wlyECw3iJrzi0AhIWg+AJUb4PlRQVW4/3XHH1LZA= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= diff --git a/pkg/sidecarproxy/metricshandler/numofrequests/metricshandler.go b/pkg/sidecarproxy/metricshandler/numofrequests/metricshandler.go index 0036df4..2ba9e5c 100644 --- a/pkg/sidecarproxy/metricshandler/numofrequests/metricshandler.go +++ b/pkg/sidecarproxy/metricshandler/numofrequests/metricshandler.go @@ -7,28 +7,16 @@ import ( "github.com/v3io/sidecar-proxy/pkg/sidecarproxy/metricshandler" "github.com/v3io/sidecar-proxy/pkg/sidecarproxy/metricshandler/abstract" - "github.com/v3io/sidecar-proxy/pkg/util" - "github.com/gorilla/websocket" - "github.com/koding/websocketproxy" "github.com/nuclio/errors" "github.com/nuclio/logger" "github.com/prometheus/client_golang/prometheus" ) -var ( - WebsocketUpgrader = util.ExtendedWebSocket{ - WebsocketUpgrader: websocket.Upgrader{ - ReadBufferSize: 1024, - WriteBufferSize: 1024, - }} -) - type metricsHandler struct { *abstract.MetricsHandler - metric *prometheus.CounterVec - httpProxy *httputil.ReverseProxy - webSocketProxy *websocketproxy.WebsocketProxy + metric *prometheus.CounterVec + proxy *httputil.ReverseProxy } func NewMetricsHandler(logger logger.Logger, @@ -74,8 +62,8 @@ func (n *metricsHandler) RegisterMetrics() error { func (n *metricsHandler) Start() error { http.HandleFunc("/", n.onRequest) - if err := n.createProxies(); err != nil { - return errors.Wrap(err, "Failed to initiate proxies") + if err := n.createProxy(); err != nil { + return errors.Wrap(err, "Failed to initiate proxy") } // adds one data point on service initialization so metric will be initialized and queryable @@ -83,18 +71,12 @@ func (n *metricsHandler) Start() error { return nil } -func (n *metricsHandler) createProxies() error { - webSocketTargetURL, err := url.Parse("ws://" + n.ForwardAddress) - if err != nil { - return errors.Wrap(err, "Failed to parse web socket forward address") - } - n.webSocketProxy = websocketproxy.NewProxy(webSocketTargetURL) - +func (n *metricsHandler) createProxy() error { httpTargetURL, err := url.Parse("http://" + n.ForwardAddress) if err != nil { return errors.Wrap(err, "Failed to parse http forward address") } - n.httpProxy = httputil.NewSingleHostReverseProxy(httpTargetURL) + n.proxy = httputil.NewSingleHostReverseProxy(httpTargetURL) return nil } @@ -125,18 +107,6 @@ func (n *metricsHandler) onRequest(res http.ResponseWriter, req *http.Request) { } func (n *metricsHandler) forwardRequest(res http.ResponseWriter, req *http.Request) error { - proxyHandler := n.getProxyHandler(res, req) - proxyHandler.ServeHTTP(res, req) + n.proxy.ServeHTTP(res, req) return nil } - -func (n *metricsHandler) getProxyHandler(res http.ResponseWriter, req *http.Request) http.Handler { - if n.isWebSocket(res, req) { - return n.webSocketProxy - } - return n.httpProxy -} - -func (n *metricsHandler) isWebSocket(res http.ResponseWriter, req *http.Request) bool { - return WebsocketUpgrader.VerifyWebSocket(res, req, nil) == nil -} diff --git a/pkg/util/util.go b/pkg/util/util.go deleted file mode 100644 index 9fe16d8..0000000 --- a/pkg/util/util.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package util - -import ( - "net/http" - "unicode/utf8" -) - -// Token octets per RFC 2616. -var isTokenOctet = [256]bool{ - '!': true, - '#': true, - '$': true, - '%': true, - '&': true, - '\'': true, - '*': true, - '+': true, - '-': true, - '.': true, - '0': true, - '1': true, - '2': true, - '3': true, - '4': true, - '5': true, - '6': true, - '7': true, - '8': true, - '9': true, - 'A': true, - 'B': true, - 'C': true, - 'D': true, - 'E': true, - 'F': true, - 'G': true, - 'H': true, - 'I': true, - 'J': true, - 'K': true, - 'L': true, - 'M': true, - 'N': true, - 'O': true, - 'P': true, - 'Q': true, - 'R': true, - 'S': true, - 'T': true, - 'U': true, - 'W': true, - 'V': true, - 'X': true, - 'Y': true, - 'Z': true, - '^': true, - '_': true, - '`': true, - 'a': true, - 'b': true, - 'c': true, - 'd': true, - 'e': true, - 'f': true, - 'g': true, - 'h': true, - 'i': true, - 'j': true, - 'k': true, - 'l': true, - 'm': true, - 'n': true, - 'o': true, - 'p': true, - 'q': true, - 'r': true, - 's': true, - 't': true, - 'u': true, - 'v': true, - 'w': true, - 'x': true, - 'y': true, - 'z': true, - '|': true, - '~': true, -} - -// skipSpace returns a slice of the string s with all leading RFC 2616 linear -// whitespace removed. -func skipSpace(s string) (rest string) { - i := 0 - for ; i < len(s); i++ { - if b := s[i]; b != ' ' && b != '\t' { - break - } - } - return s[i:] -} - -// nextToken returns the leading RFC 2616 token of s and the string following -// the token. -func nextToken(s string) (token, rest string) { - i := 0 - for ; i < len(s); i++ { - if !isTokenOctet[s[i]] { - break - } - } - return s[:i], s[i:] -} - -// equalASCIIFold returns true if s is equal to t with ASCII case folding as -// defined in RFC 4790. -func equalASCIIFold(s, t string) bool { - for s != "" && t != "" { - sr, size := utf8.DecodeRuneInString(s) - s = s[size:] - tr, size := utf8.DecodeRuneInString(t) - t = t[size:] - if sr == tr { - continue - } - if 'A' <= sr && sr <= 'Z' { - sr = sr + 'a' - 'A' - } - if 'A' <= tr && tr <= 'Z' { - tr = tr + 'a' - 'A' - } - if sr != tr { - return false - } - } - return s == t -} - -// tokenListContainsValue returns true if the 1#token header with the given -// name contains a token equal to value with ASCII case folding. -func tokenListContainsValue(header http.Header, name string, value string) bool { -headers: - for _, s := range header[name] { - for { - var t string - t, s = nextToken(skipSpace(s)) - if t == "" { - continue headers - } - s = skipSpace(s) - if s != "" && s[0] != ',' { - continue headers - } - if equalASCIIFold(t, value) { - return true - } - if s == "" { - continue headers - } - s = s[1:] - } - } - return false -} diff --git a/pkg/util/websocket.go b/pkg/util/websocket.go deleted file mode 100644 index 03ee689..0000000 --- a/pkg/util/websocket.go +++ /dev/null @@ -1,43 +0,0 @@ -package util - -import ( - "net/http" - - "github.com/gorilla/websocket" - "github.com/nuclio/errors" -) - -type ExtendedWebSocket struct { - WebsocketUpgrader websocket.Upgrader -} - -func (wu *ExtendedWebSocket) VerifyWebSocket(w http.ResponseWriter, r *http.Request, responseHeader http.Header) error { - const badHandshake = "websocket: the client is not using the websocket protocol: " - - if !tokenListContainsValue(r.Header, "Connection", "upgrade") { - return errors.New(badHandshake + "'upgrade' token not found in 'Connection' header") - } - - if !tokenListContainsValue(r.Header, "Upgrade", "websocket") { - return errors.New(badHandshake + "'websocket' token not found in 'Upgrade' header") - } - - if r.Method != "GET" { - return errors.New(badHandshake + "request method is not GET") - } - - if !tokenListContainsValue(r.Header, "Sec-Websocket-Version", "13") { - return errors.New("websocket: unsupported version: 13 not found in 'Sec-Websocket-Version' header") - } - - if _, ok := responseHeader["Sec-Websocket-Extensions"]; ok { - return errors.New("websocket: application specific 'Sec-WebSocket-Extensions' headers are unsupported") - } - - challengeKey := r.Header.Get("Sec-Websocket-Key") - if challengeKey == "" { - return errors.New("websocket: not a websocket handshake: `Sec-WebSocket-Key' header is missing or blank") - } - - return nil -}