Fix Pingora forwarding Connection: closed to upstream, causing the co… #713
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I discovered an important bug in Pingora: it forwards hop-by-hop headers directly to upstream servers, which violates HTTP specifications (RFC 7230 and RFC 7540) and causes serious performance degradation.
The most critical case is when clients send
Connection: close, which Pingora incorrectly forwards to the upstream server. This causes the connection between Pingora and upstream to close unnecessarily, breaking connection reuse and severely impacting performance.Problem Demonstration
Request from client:
What Pingora currently forwards to upstream (WRONG):
Correct behavior (should be removed):
Root Cause Analysis
Through code analysis, the problem occurs in several places:
HTTP/1 → HTTP/1 forwarding path (
pingora-proxy/src/proxy_h1.rs)HTTP/2 forwarding path (
pingora-proxy/src/proxy_h2.rs)Lack of unified handling mechanism
RFC Specification Requirements
According to RFC 7230 (HTTP/1.1 Message Syntax) and RFC 7540 (HTTP/2), the following headers are hop-by-hop headers that proxies MUST remove:
ConnectionKeep-AliveProxy-AuthenticateProxy-AuthorizationTETrailersTransfer-EncodingUpgradeAdditionally, RFC 7230 specifies that the
Connectionheader can declare other headers as hop-by-hop (e.g.,Connection: close, X-Custom-HeadermeansX-Custom-Headershould also be removed).Solution
My fix includes the following:
1. Add unified hop-by-hop header removal method
Add new method
remove_hop_by_hop_headers()toRequestHeaderinpingora-http/src/lib.rs:This method handles:
2. Apply to all request forwarding paths
proxy_h1.rs): Callremove_hop_by_hop_headers()before forwardingproxy_h2.rs): Unified use of new method replacing manual removal3. Add comprehensive test cases
Add 3 test cases verifying:
Modified Files
pingora-http/src/lib.rs
remove_hop_by_hop_headers()method (~40 lines)pingora-proxy/src/proxy_h1.rs
pingora-proxy/src/proxy_h2.rs
Test Verification
All tests pass:
Performance Impact
In high-traffic scenarios, the connection reuse improvement will provide very noticeable performance gains.
Backward Compatibility
This is a bug fix, not a new feature. Theoretically it's a breaking change, but will only affect code that relied on the incorrect behavior (forwarding hop-by-hop headers). Correct code is unaffected.
Verification
You can verify the fix by:
socat TCP-LISTEN:3000,reuseaddr,fork -)Connection: closeConnectionheaderReferences
RFC 7230 Section 6.1: Connection Header
https://tools.ietf.org/html/rfc7230#section-6.1
RFC 7540 Section 8.1.2: HTTP/2 Connection-Specific Headers
https://tools.ietf.org/html/rfc7540#section-8.1.2
MDN: Hop-by-hop headers
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#hop-by-hop_headers
Summary
This PR fixes a critical compliance and performance issue where Pingora was violating HTTP specifications by forwarding hop-by-hop headers. The fix is minimal, well-tested, and brings Pingora into full RFC 7230 and RFC 7540 compliance while significantly improving performance through maintained connection reuse.