diff options
Diffstat (limited to 'modules/caddyhttp/reverseproxy/reverseproxy.go')
-rw-r--r-- | modules/caddyhttp/reverseproxy/reverseproxy.go | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/modules/caddyhttp/reverseproxy/reverseproxy.go b/modules/caddyhttp/reverseproxy/reverseproxy.go index 30d9af101..46f1fe5bb 100644 --- a/modules/caddyhttp/reverseproxy/reverseproxy.go +++ b/modules/caddyhttp/reverseproxy/reverseproxy.go @@ -17,6 +17,8 @@ package reverseproxy import ( "bytes" "context" + "crypto/rand" + "encoding/base64" "encoding/json" "errors" "fmt" @@ -394,6 +396,23 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyht return caddyhttp.Error(http.StatusInternalServerError, fmt.Errorf("preparing request for upstream round-trip: %v", err)) } + // websocket over http2, assuming backend doesn't support this, the request will be modified to http1.1 upgrade + // TODO: once we can reliably detect backend support this, it can be removed for those backends + if r.ProtoMajor == 2 && r.Method == http.MethodConnect && r.Header.Get(":protocol") != "" { + clonedReq.Header.Del(":protocol") + // keep the body for later use. http1.1 upgrade uses http.NoBody + caddyhttp.SetVar(clonedReq.Context(), "h2_websocket_body", clonedReq.Body) + clonedReq.Body = http.NoBody + clonedReq.Method = http.MethodGet + clonedReq.Header.Set("Upgrade", r.Header.Get(":protocol")) + clonedReq.Header.Set("Connection", "Upgrade") + key := make([]byte, 16) + _, randErr := rand.Read(key) + if randErr != nil { + return randErr + } + clonedReq.Header["Sec-WebSocket-Key"] = []string{base64.StdEncoding.EncodeToString(key)} + } // we will need the original headers and Host value if // header operations are configured; this is so that each |