use already buffered response if possible when intercepting

This commit is contained in:
WeidiDeng 2025-05-20 10:39:27 +08:00
parent a76d005a94
commit aafecf9d66
No known key found for this signature in database
GPG Key ID: 25F87CE1741EC7CD

View File

@ -17,6 +17,7 @@ package intercept
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
@ -175,10 +176,35 @@ func (ir Intercept) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddy
c.Write(zap.Int("handler", rec.handlerIndex)) c.Write(zap.Int("handler", rec.handlerIndex))
} }
// pass the request through the response handler routes // response recorder doesn't create a new copy of the original headers, they're
return rec.handler.Routes.Compile(next).ServeHTTP(w, r) // present in the original response writer
// create a new recorder to see if any response body from the new handler is present,
// if not, use the already buffered response body
recorder := caddyhttp.NewResponseRecorder(w, nil, nil)
if err := rec.handler.Routes.Compile(emptyHandler).ServeHTTP(recorder, r); err != nil {
return err
}
// no new response status and the status is not 0
if recorder.Status() == 0 && rec.Status() != 0 {
w.WriteHeader(rec.Status())
}
// no new response body and there is some in the original response
// TODO: what if the new response doesn't have a body by design?
// see: https://github.com/caddyserver/caddy/pull/6232#issue-2235224400
if recorder.Size() == 0 && buf.Len() > 0 {
_, err := io.Copy(w, buf)
return err
}
return nil
} }
// this handler does nothing because everything we need is already buffered
var emptyHandler caddyhttp.Handler = caddyhttp.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) error {
return nil
})
// UnmarshalCaddyfile sets up the handler from Caddyfile tokens. Syntax: // UnmarshalCaddyfile sets up the handler from Caddyfile tokens. Syntax:
// //
// intercept [<matcher>] { // intercept [<matcher>] {