mirror of
https://github.com/caddyserver/caddy.git
synced 2025-10-25 07:49:19 -04:00
reverseproxy: Use http1.1 upgrade for websocket for extended connect of http2 and http3 (#7305)
Co-authored-by: WeidiDeng <weidi_deng@icloud.com>
This commit is contained in:
parent
10ac7da037
commit
7fb39ec1e5
@ -409,12 +409,16 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyht
|
|||||||
return caddyhttp.Error(http.StatusInternalServerError,
|
return caddyhttp.Error(http.StatusInternalServerError,
|
||||||
fmt.Errorf("preparing request for upstream round-trip: %v", err))
|
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
|
|
||||||
|
// websocket over http2 or http3 if extended connect is enabled, assuming backend doesn't support this, the request will be modified to http1.1 upgrade
|
||||||
|
// Both use the same upgrade mechanism: server advertizes extended connect support, and client sends the pseudo header :protocol in a CONNECT request
|
||||||
|
// The quic-go http3 implementation also puts :protocol in r.Proto for CONNECT requests (quic-go/http3/headers.go@70-72,185,203)
|
||||||
// TODO: once we can reliably detect backend support this, it can be removed for those backends
|
// 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") == "websocket" {
|
if (r.ProtoMajor == 2 && r.Method == http.MethodConnect && r.Header.Get(":protocol") == "websocket") ||
|
||||||
|
(r.ProtoMajor == 3 && r.Method == http.MethodConnect && r.Proto == "websocket") {
|
||||||
clonedReq.Header.Del(":protocol")
|
clonedReq.Header.Del(":protocol")
|
||||||
// keep the body for later use. http1.1 upgrade uses http.NoBody
|
// keep the body for later use. http1.1 upgrade uses http.NoBody
|
||||||
caddyhttp.SetVar(clonedReq.Context(), "h2_websocket_body", clonedReq.Body)
|
caddyhttp.SetVar(clonedReq.Context(), "extended_connect_websocket_body", clonedReq.Body)
|
||||||
clonedReq.Body = http.NoBody
|
clonedReq.Body = http.NoBody
|
||||||
clonedReq.Method = http.MethodGet
|
clonedReq.Method = http.MethodGet
|
||||||
clonedReq.Header.Set("Upgrade", "websocket")
|
clonedReq.Header.Set("Upgrade", "websocket")
|
||||||
|
|||||||
@ -94,9 +94,9 @@ func (h *Handler) handleUpgradeResponse(logger *zap.Logger, wg *sync.WaitGroup,
|
|||||||
conn io.ReadWriteCloser
|
conn io.ReadWriteCloser
|
||||||
brw *bufio.ReadWriter
|
brw *bufio.ReadWriter
|
||||||
)
|
)
|
||||||
// websocket over http2, assuming backend doesn't support this, the request will be modified to http1.1 upgrade
|
// websocket over http2 or http3 if extended connect is enabled, 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
|
// TODO: once we can reliably detect backend support this, it can be removed for those backends
|
||||||
if body, ok := caddyhttp.GetVar(req.Context(), "h2_websocket_body").(io.ReadCloser); ok {
|
if body, ok := caddyhttp.GetVar(req.Context(), "extended_connect_websocket_body").(io.ReadCloser); ok {
|
||||||
req.Body = body
|
req.Body = body
|
||||||
rw.Header().Del("Upgrade")
|
rw.Header().Del("Upgrade")
|
||||||
rw.Header().Del("Connection")
|
rw.Header().Del("Connection")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user