mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 20:09:58 +00:00
TUN-3764: Actively flush data for TCP streams
This commit is contained in:
@@ -97,44 +97,25 @@ func (c *http2Connection) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
c.activeRequestsWG.Add(1)
|
||||
defer c.activeRequestsWG.Done()
|
||||
|
||||
respWriter := &http2RespWriter{
|
||||
r: r.Body,
|
||||
w: w,
|
||||
}
|
||||
flusher, isFlusher := w.(http.Flusher)
|
||||
if !isFlusher {
|
||||
c.observer.log.Error().Msgf("%T doesn't implement http.Flusher", w)
|
||||
respWriter.WriteErrorResponse()
|
||||
connType := determineHTTP2Type(r)
|
||||
respWriter, err := newHTTP2RespWriter(r, w, connType)
|
||||
if err != nil {
|
||||
c.observer.log.Error().Msg(err.Error())
|
||||
return
|
||||
}
|
||||
respWriter.flusher = flusher
|
||||
|
||||
switch {
|
||||
case isControlStreamUpgrade(r):
|
||||
respWriter.shouldFlush = true
|
||||
if err := c.serveControlStream(r.Context(), respWriter); err != nil {
|
||||
respWriter.WriteErrorResponse()
|
||||
}
|
||||
return
|
||||
|
||||
case isWebsocketUpgrade(r):
|
||||
respWriter.shouldFlush = true
|
||||
var proxyErr error
|
||||
switch connType {
|
||||
case TypeControlStream:
|
||||
proxyErr = c.serveControlStream(r.Context(), respWriter)
|
||||
case TypeWebsocket:
|
||||
stripWebsocketUpgradeHeader(r)
|
||||
if err := c.config.OriginProxy.Proxy(respWriter, r, TypeWebsocket); err != nil {
|
||||
respWriter.WriteErrorResponse()
|
||||
}
|
||||
return
|
||||
|
||||
case IsTCPStream(r):
|
||||
if err := c.config.OriginProxy.Proxy(respWriter, r, TypeTCP); err != nil {
|
||||
respWriter.WriteErrorResponse()
|
||||
}
|
||||
return
|
||||
|
||||
proxyErr = c.config.OriginProxy.Proxy(respWriter, r, TypeWebsocket)
|
||||
default:
|
||||
if err := c.config.OriginProxy.Proxy(respWriter, r, TypeHTTP); err != nil {
|
||||
respWriter.WriteErrorResponse()
|
||||
}
|
||||
proxyErr = c.config.OriginProxy.Proxy(respWriter, r, connType)
|
||||
}
|
||||
if proxyErr != nil {
|
||||
respWriter.WriteErrorResponse()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +155,25 @@ type http2RespWriter struct {
|
||||
shouldFlush bool
|
||||
}
|
||||
|
||||
func newHTTP2RespWriter(r *http.Request, w http.ResponseWriter, connType Type) (*http2RespWriter, error) {
|
||||
flusher, isFlusher := w.(http.Flusher)
|
||||
if !isFlusher {
|
||||
respWriter := &http2RespWriter{
|
||||
r: r.Body,
|
||||
w: w,
|
||||
}
|
||||
respWriter.WriteErrorResponse()
|
||||
return nil, fmt.Errorf("%T doesn't implement http.Flusher", w)
|
||||
}
|
||||
|
||||
return &http2RespWriter{
|
||||
r: r.Body,
|
||||
w: w,
|
||||
flusher: flusher,
|
||||
shouldFlush: connType.shouldFlush(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (rp *http2RespWriter) WriteRespHeaders(status int, header http.Header) error {
|
||||
dest := rp.w.Header()
|
||||
userHeaders := make(http.Header, len(header))
|
||||
@@ -243,6 +243,19 @@ func (rp *http2RespWriter) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func determineHTTP2Type(r *http.Request) Type {
|
||||
switch {
|
||||
case isWebsocketUpgrade(r):
|
||||
return TypeWebsocket
|
||||
case IsTCPStream(r):
|
||||
return TypeTCP
|
||||
case isControlStreamUpgrade(r):
|
||||
return TypeControlStream
|
||||
default:
|
||||
return TypeHTTP
|
||||
}
|
||||
}
|
||||
|
||||
func isControlStreamUpgrade(r *http.Request) bool {
|
||||
return r.Header.Get(internalUpgradeHeader) == controlStreamUpgrade
|
||||
}
|
||||
|
Reference in New Issue
Block a user