-
-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Content-Encoding header missing with reverse-proxied chunked response #4314
Comments
I think more related to #4266. /cc @francislavoie |
I experienced the same on Debian 11 using the official Caddy repo. I had to downgrade to 2.4.3. |
Thanks for the replication case @ueffel, very appreciated. Running with
So I think the bug is actually on that line, but it was only revealed from the recent changes to stdlib which cause immediate flushing in certain cases: caddy/modules/caddyhttp/responsewriter.go Lines 166 to 169 in f43fd6f
|
Gist of it is multiple calls to The change in e6c29ce#diff-287933cf508d4f4a33e4e0ac918639f44b9967505681131a29c82d608c2dfe57R152-R156 was necessary to fix a different bug (and was taken from the Go stdlib) but fixing that caused a different bug elsewhere. I did a bit of tracing with Key places to look at and add some debug statements to track it down:
|
I think a premature I think ignoring all diff --git a/modules/caddyhttp/encode/encode.go b/modules/caddyhttp/encode/encode.go
index a7abb3f90d3ec510249415de71cb3a697bc2632b..e7294f35f0fe4f94663c4e06cbb2ff6e895c09c6 100644
--- a/modules/caddyhttp/encode/encode.go
+++ b/modules/caddyhttp/encode/encode.go
@@ -182,6 +182,7 @@ type responseWriter struct {
buf *bytes.Buffer
config *Encode
statusCode int
+ wroteHeader bool
}
// WriteHeader stores the status to write when the time comes
@@ -195,6 +196,17 @@ func (enc *Encode) Match(rw *responseWriter) bool {
return enc.Matcher.Match(rw.statusCode, rw.Header())
}
+func (rw *responseWriter) Flush() {
+ if !rw.wroteHeader {
+ // flushing the underlying ResponseWriter will write header and status code
+ // but we need to delay that until we can determine if we must encode and
+ // therefore send the Content-Encoding header
+ // this happens in the first call to rw.Write
+ return
+ }
+ rw.ResponseWriterWrapper.Flush()
+}
+
// Write writes to the response. If the response qualifies,
// it is encoded using the encoder, which is initialized
// if not done so already.
@@ -225,6 +237,7 @@ func (rw *responseWriter) Write(p []byte) (int, error) {
if rw.statusCode > 0 {
rw.ResponseWriter.WriteHeader(rw.statusCode)
rw.statusCode = 0
+ rw.wroteHeader = true
}
switch {
@@ -271,6 +284,7 @@ func (rw *responseWriter) Close() error {
// that rely on If-None-Match, for example
rw.ResponseWriter.WriteHeader(rw.statusCode)
rw.statusCode = 0
+ rw.wroteHeader = true
}
if rw.w != nil {
err2 := rw.w.Close()
|
Yeah, that sounds right to me! Thanks for looking into it @ueffel, very much appreciated! If you're like to make a PR with that, that'd be great (and if you have time, an integration test to cover this would be great as well) |
* encode: ignore flushing until after first write (fix #4314) The first write will determine if encoding has to be done and will add an Content-Encoding. Until then Flushing has to be delayed so the Content-Encoding header can be added before headers and status code is written. (A passthrough flush would write header and status code) * Update modules/caddyhttp/encode/encode.go Co-authored-by: Matt Holt <[email protected]>
Thank you for the investigation, both of you, and for the quick fix! Tricky tricky. Web servers are hard. |
Affected version: 2.4.4
I noticed that the
Content-Encoding
header is missing on reverse proxied responses when they are big enough so they are transferred in chunks. The response is encoded but the header isn't sent, which results in garbled mess.Example Caddyfile:
Request / Response:
If the
respond
directive is one line shorter the Request / Response is ok:I think responsible are the following lines:
e6c29ce#diff-287933cf508d4f4a33e4e0ac918639f44b9967505681131a29c82d608c2dfe57R152-R156
If comment them out, everything is fine.
Other headers don't seems to be affected, but I'm not sure.
Maybe related to #3997
For the record with version 2.4.3 everything is fine too.
The text was updated successfully, but these errors were encountered: