-
Notifications
You must be signed in to change notification settings - Fork 108
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
Fix multiple header writes for connect unary on error #726
Conversation
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.
LGTM
if err := conn.Receive(&msg2); err == nil { | ||
return nil, NewError(CodeUnimplemented, fmt.Errorf("unary %s has multiple messages", what)) | ||
} else if err != nil && !errors.Is(err, io.EOF) { | ||
if err := conn.Receive(&msg2); !errors.Is(err, io.EOF) { |
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.
Unrelated to the change but the error check err != nil
was superfluous, so simplified to the happy path first.
@@ -757,7 +755,7 @@ func (hc *connectUnaryHandlerConn) getHTTPMethod() string { | |||
return hc.request.Method | |||
} | |||
|
|||
func (hc *connectUnaryHandlerConn) writeResponseHeader(err error) { | |||
func (hc *connectUnaryHandlerConn) mergeResponseHeader(err error) { |
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.
Renamed to mergeResponseHeaders
as this doesn't trigger a write.
// If the handler received a GET request and the resource hasn't changed, | ||
// return a 304. | ||
if len(hc.peer.Query) > 0 && IsNotModifiedError(err) { | ||
hc.responseWriter.WriteHeader(http.StatusNotModified) | ||
return hc.request.Body.Close() | ||
} | ||
} | ||
if err == nil { | ||
if err == nil || hc.marshaler.wroteHeader { |
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.
We could error here to report to the Close
that the error wasn't encoded. I've left for now, as a best effort solution.
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.
TY for the quick fix!
On error a connect unary handler will call
Close(err)
to send the final error. For non-nil errors this will always attempt to encode the header status by callingWriteHeader
. If the body has already been written this triggers the following log viahttp.Server
:The common case for this superfluous log is when a message send is interrupted, due to a context cancel or other write error, and the error is then attempting to re-encode the headers and body.
This PR now moves the
wroteBody
check to awroteHeader
check on the unmarshaller. When any payload is sent, including a nil field for header only, we now stop attempting to encode any following errors, as it would be superfluous.