-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Description
I've been using the replace-response module alongside reverse_proxy
recently and observed incorrect status codes being returned from the proxy, e.g., the origin responded with a 404
and the proxy responds with a 200
.
flowchart
UA --> |Request| reverse_proxy --> |Request| Origin
Origin --> |404 Origin Response| reverse_proxy --> |200 Proxy Response| UA
After a bit of debugging, it looks like the call to copyResponse results in a flush action here, which causes a 200
status code to be written after http.ResponseController.Flush
unwraps and writes to the replace-response's replaceWriter caddyhttp.responseRecorder.
edit: I mistakenly thought I had streaming enabled, which is why I originally referenced replaceWriter
.
A potential fix would be to check for an Unwrap
method on the response writer alongside the base one in reverseproxy.go. I've tested this locally but I'm not sure if it's the best solution. I'm also not entirely sure if this is even considered a bug. I know that flush_interval
is available as a configuration and I haven't tested if it solves the issue, but it definitely was not an obvious solution to the behavior if it is.
edit: Setting flush_interval
does not seem to correct the issue.
type unwrapper interface {
Unwrap() http.ResponseWriter
}
func (h *Handler) finalizeResponse {
//...
// Line 955
rw.WriteHeader(res.StatusCode)
// Unwrap and write non-200 status code
if rw, ok := rw.(unwrapper); res.StatusCode != http.StatusOK && ok {
rw.Unwrap().WriteHeader(res.StatusCode)
}
if h.VerboseLogs {
logger.Debug("wrote header")
}
err := h.copyResponse(rw, res.Body, h.flushInterval(req, res), logger)
//...
}