-
Notifications
You must be signed in to change notification settings - Fork 18k
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
proposal: x/net/http2: distinguish no body from empty body #53894
Comments
HTTP, so far as I know, doesn't make any distinction between "no body" and "empty body". The choice to send the If we were to support this, I think there needs to be compelling evidence that this is of general value. |
This proposal has been added to the active column of the proposals project |
@shreyas44, can you please give more detail about this? Which servers? What kinds of differentiation? @neild's comment suggests that we probably shouldn't do this without a compelling reason. |
@neild @rsc apologies for the inactivity.
You're right that for the majority of the cases this doesn't matter and should remain an implementation detail. The only use case I can think of right now is ours - trying to read and replicate the behaviour of a client that does differentiate between the two (Go being one of them as mentioned previously, although I'm not sure whether that's intentional). We could also use
What caused issues for us was an AkamaiGhost server. When sending an empty body, we received a 403 forbidden response but when sending no body we received a successful response. Cloudflare also seems to differentiate between the two. The crux of the linked post is that cloudflare doesn't add a |
I think the terms "no body" and "empty body" are adding confusion here. There is no such distinction in HTTP. All HTTP requests and responses have a payload, and the payload may have a length of zero. There aren't different types of zero-length payloads. What you're requesting is a way to distinguish between HTTP/2 streams with a zero-length payload that send the This is a distinguishable property of HTTP/2 streams, just as the division of the payload between data frames is, but HTTP/2 doesn't draw a semantic distinction in either case and I don't think we should be exposing either in the |
Is there any indication from Akamai or Cloudflare that this behavior is intentional, rather than just a bug in their implementations? If this is just a server-side bug in those two systems, it would be better for Go not to expose the difference and open the door to more such bugs. |
As far as I know, neither Akamai nor Cloudflare have mentioned this issue anywhere. You might be right in that it's a bug and not intentional.
Fair. On the note of preventing bugs, I think |
Do you have any suggestions on how we could do this without having to fork |
I'm afraid not. The Perhaps there's a case to be made for this feature (if it's something that other HTTP/2 implementations commonly expose, that would be an argument that |
@neild and I are both mildly but not strongly opposed to this. We sympathize with having to interop with broken servers. If we do this, it should be locked in with a test, have similar behavior between HTTP/1 and HTTP/2, and be documented. I also want to see first a summary table of the current and proposed states of the server behavior for all combinations of:
|
It sounds like this is blocked on gathering the data table that @bradfitz asked for in the previous message, if we want to move forward. |
@shreyas44, any interest in collecting the data Brad asked for in #53894 (comment) ? |
Placed on hold. |
Issue
A server cannot differentiate between the below two scenarios:
END_STREAM
andEND_HEADERS
flag and no data frame was sent after thatEND_HEADERS
flag. Subsequently, an empty data frame with anEND_STREAM
flag is sent.When reading the body on
http.Request
, both immediately returnio.EOF
and 0 bytes are read.Proposal
Create
http2.NoBody
andhttp2.EmptyBody
to represent the two scenarios and set thereq.Body
to them.http2.NoBody
can equalhttp.NoBody
as well.Use Case
Some servers differentiate between the two kinds of requests. We're running a MITM proxy that needs to read which kind of request a client is making and forward the same to the target server.
Alternatives Considered
Add a method to
http.Request
(namedReadDataFrame
?) that returns whether or not a client sent a data frame.Personally, I prefer adding
http2.NoBody
andhttp2.EmptyBody
.Additional Notes
req.Body
is set tonil
orhttp.NoBody
, no data frame is sent byhttp2.Transport
. If it's set to another reader that returns 0 bytes (ex:ioutil.NopCloser(strings.NewReader(""))
), then an empty data frame is sent. This gives a way to differentiate between the two scenarios when sending requests but not when accepting requests throughhttp.Server
orhttp2.Server
The text was updated successfully, but these errors were encountered: