-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
net/http/httptrace: WroteHeaders should be called after flush or provide an option to do so #60576
Comments
CC @neild |
We could move The HTTP/2 client calls Currently, a trace always follows a sequence of In addition, calling Perhaps a better approach would be to add a distinguishable error condition to
The flush in this case writes the headers before starting to write the request body, to ensure that headers go out if the I could understand wanting a way to disable the header flush, to let headers go out in the same TCP packet as the start of the body, but I don't know why you'd want to add flushes that aren't performed now. |
If the Edit: @domdom82 and I are working together and discussed this issue before opening it. |
It's here. Sure, it would help a lot if the unwrapped error types would be returned. Edit: @neild the unwrapping of more specific errors such as |
Where we are coming from
We have a setup where an L4 proxy (Envoy) is between the go client and the target server. When the client opens a connection to the server, the proxy first accepts the TCP connection and does a TLS handshake at the frontend before trying to proxy the request forward to the backend.
If the backend is dead, the proxy will immediately close the frontend connection again. This results in a broken pipe at the client, because it was just about to send HTTP data and will now receive an io.EOF error (actually, it is a nothingWrittenError unwrapped to an EOF but I digress..)
The issue we need to solve
Now the issue for us is, we would like to know if we can safely retry the request or not. For GET/HEAD/OPTIONS etc. that's easy.
However, for POST/PUT requests we need to know if the server has actually received anything (= don't retry) or not (= retry).
Since all we get is an EOF, we can't be sure.
httptrace
In an attempt to mitigate the situation we turned to httptrace and its
GotConn
andWroteHeaders
callbacks.The idea was to use them as indicators if any part of the request has actually made it to the backend server or not. Now, the problem with
WroteHeaders
is that it is called when the request headers have been written to the bufio.Writer NOT the wire.For us, this is pretty useless because of course a write to an in-memory buffer always succeeds. It does not tell you anything about whether or not the headers were actually sent to the target server. I question the usefulness of that callback.
I noticed that further down the headers are actually flushed if the request is a POST with a body and some other quirky conditions (I'll get to that later).
My suggestion is to move the call to
trace.WroteHeaders()
below the (potential) flush to have some safety that the server has actually seen the headers before we claim that we wrote them.An alternative could be the addition of a new
FlushedHeaders
callback in httptrace that is specific to this use case and is put here, i.e. called when no error occurred during flushing.Now about those 'quirky' flushing conditions...
I've read into the commit that introduced this behavior and wondered why it was done this way. Like the comment suggests, we should flush "just in case the server needs the headers early" - which is the case for us. However, we would like to be able to flush on all requests, including e.g. POSTs without a body. So can't we just make
FlushHeaders
a configurable field ofRequest
and pass it down to thetransferWriter
? This way the client can decide if it wants to send early headers to the server, instead of having this decision taken away by the SDK.tl;dr
Flush()
httptrace.FlushedHeaders
callback that is called afterFlush()
FlushHeaders
an option for requests so that the client can decide if their want to send headers early or notThe text was updated successfully, but these errors were encountered: