-
Notifications
You must be signed in to change notification settings - Fork 845
Fix http2 content-length header check (#12747) #12748
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
base: master
Are you sure you want to change the base?
Conversation
|
Good catch. However, as the RFC says, "A response that is defined to have no payload" is the condition. It looks like your change allows arbitrarily response that have no payload. |
|
My understanding of the RFC is that the condition defining a valid response without payload is the stream ending at header or continuation frame. However, if you prefer we could skip this check in rcv_header_frame and rcv_continuation_frame if and only if they are not trailing headers (since trailing headers implies that data frames where received) Here is an alternative condition that could be used: if (stream->receive_end_stream && stream->trailing_header_is_possible() && !stream->payload_length_is_valid()) {In both:
|
|
I don't think what frame carries END_STREAM flag matters. A DATA frame that carries just END_STREAM flag (no payload) is valid. If a request is GET and the response has |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes HTTP/2 HEAD method responses that include Content-Length headers. Previously, these responses incorrectly returned 502 errors when the Content-Length didn't match the (zero) payload length. Per RFC 7540 section 8.1.2.6, HTTP/2 responses defined to have no payload (such as HEAD responses) can legitimately have non-zero Content-Length headers even though no DATA frames are included.
Key Changes:
- Modified
payload_length_is_valid()to allow responses with zero-length payloads regardless of Content-Length value - Updated warning condition to only trigger when both content_length and data_length are non-zero but mismatched
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
include/proxy/http2/Http2Stream.h
Outdated
| if (content_length != 0 && data_length != 0 && content_length != data_length) { | ||
| Warning("Bad payload length content_length=%d data_legnth=%d session_id=%" PRId64, content_length, | ||
| static_cast<int>(data_length), _proxy_ssn->connection_id()); | ||
| } | ||
| return content_length == 0 || content_length == data_length; | ||
| return content_length == 0 || data_length == 0 || content_length == data_length; |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fix for RFC 7540 section 8.1.2.6 compliance (allowing non-zero Content-Length with zero-length payloads) lacks test coverage. Consider adding an HTTP/2 test case that verifies HEAD responses with Content-Length headers are handled correctly, specifically testing that a HEAD response with Content-Length greater than 0 but data_length of 0 does not return a 502 error.
|
You're right I misunderstood the RFC, I went back to it and in my understanding, the only cases where a non-zero 'Content-Lenght' header without payload is allowed are:
From Section 3.3.2 of [RFC7230] It indeed means that, while other types of request and response may have an empty payload (or data_length == 0), they must not have a Here is a proposal to check that the current frame is part of an HEAD response that we could use in rcv_headers_frame and rcv_continuation_frame: My understanding is that is_outbound_connection represents communication with origin which in case of receiving frame means response from origin I think the same fields can be used to know if the frame is part of a response to a conditional GET request, however to find the http status code seems trickier since the response headers are not parsed yet as we just received the frame and are still validating it. Maybe we could only fix HEAD request for the moment, does the above conditional statement work for you ? |
Correct.
The proposed condition looks fine. Since those are accessible from |
Fix issue where in HTTP2 response defined to have no payload like HEAD or 304 reponse to conditional GET were failing with 502 status when having non-zero Content-Length header. According to the RFC they may have Content-length representing the size the payload would have in the case of a 200 regular GET response. See https://datatracker.ietf.org/doc/html/rfc7540#section-8.1.2.6
c26cc51 to
7476be7
Compare
HEAD method with "Content-Length" header was returning 502 code because header differs from payload length as there is no payload in this case.
See https://datatracker.ietf.org/doc/html/rfc7540#section-8.1.2.6
Fixes #12747
The change fixes the behavior by having
payload_length_is_valid()return true ifdata_lengthis 0 meaning that the response has no payload, allowing for non-zero 'Content-Length' in this case as specified in the rfc.