Describe the bug
When a proxy overrides a 204 or 304 status code to 200 in response_filter, response_body_filter is never called, making it impossible to inject a synthesized body.
The root cause has two parts:
-
Protocol layer: The H1 client initializes body_reader to 0 for 204/304 responses, so the header task is emitted with end=true and no HttpTask::Body is ever produced.
-
Proxy layer: In the H1 path, no_body is computed before response_filter is called, so even if the user changes the status code, chunked encoding is not added. The H2 path already has the correct ordering.
Since no HttpTask::Body task is generated, response_body_filter has no opportunity to run.
Pingora info
Pingora version: 0.8.0 (commit 1d93711)
Rust version: rustc 1.94.1
Operating system version: macOS 26
Steps to reproduce
async fn response_filter(&self, _session: &mut Session, response: &mut ResponseHeader, ctx: &mut Self::CTX) -> Result<()> {
if response.status.as_u16() == 204 {
response.set_status(200)?;
ctx.patch = true;
}
Ok(())
}
fn response_body_filter(&self, _session: &mut Session, body: &mut Option<Bytes>, end_of_stream: bool, ctx: &mut Self::CTX) -> Result<Option<Duration>> {
if end_of_stream && ctx.patch {
*body = Some(Bytes::from("<synthesized body/>"));
}
Ok(None)
}
Expected results
After changing the status from 204/304 to 200 in response_filter, response_body_filter should be called with end_of_stream=true, allowing the user to inject body content.
Observed results
response_body_filter is never called. The downstream client receives a 200 response with no body.
Additional context
The H2 path (proxy_h2.rs) already calls response_filter before computing no_body, but still has the same issue because the upstream eos=true flag prevents any HttpTask::Body from being generated.
Describe the bug
When a proxy overrides a 204 or 304 status code to 200 in
response_filter,response_body_filteris never called, making it impossible to inject a synthesized body.The root cause has two parts:
Protocol layer: The H1 client initializes
body_readerto 0 for 204/304 responses, so the header task is emitted withend=trueand noHttpTask::Bodyis ever produced.Proxy layer: In the H1 path,
no_bodyis computed beforeresponse_filteris called, so even if the user changes the status code, chunked encoding is not added. The H2 path already has the correct ordering.Since no
HttpTask::Bodytask is generated,response_body_filterhas no opportunity to run.Pingora info
Pingora version: 0.8.0 (commit 1d93711)
Rust version: rustc 1.94.1
Operating system version: macOS 26
Steps to reproduce
Expected results
After changing the status from 204/304 to 200 in
response_filter,response_body_filtershould be called withend_of_stream=true, allowing the user to inject body content.Observed results
response_body_filteris never called. The downstream client receives a 200 response with no body.Additional context
The H2 path (
proxy_h2.rs) already callsresponse_filterbefore computingno_body, but still has the same issue because the upstreameos=trueflag prevents anyHttpTask::Bodyfrom being generated.