Skip to content

Fix multiple header writes for connect unary on error#726

Merged
emcfarlane merged 2 commits intomainfrom
ed/fixMultiHeaderWrite
Apr 17, 2024
Merged

Fix multiple header writes for connect unary on error#726
emcfarlane merged 2 commits intomainfrom
ed/fixMultiHeaderWrite

Conversation

@emcfarlane
Copy link
Contributor

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 calling WriteHeader. If the body has already been written this triggers the following log via http.Server:

http: superfluous response.WriteHeader call from connectrpc.com/connect.(*connectUnaryHandlerConn).Close (protocol_connect.go:743)

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 a wroteHeader 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.

Copy link
Member

@jhump jhump left a 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) {
Copy link
Contributor Author

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.

}

func (hc *connectUnaryHandlerConn) writeResponseHeader(err error) {
func (hc *connectUnaryHandlerConn) mergeResponseHeader(err error) {
Copy link
Contributor Author

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.

@emcfarlane emcfarlane marked this pull request as ready for review April 17, 2024 19:52
}
}
if err == nil {
if err == nil || hc.marshaler.wroteHeader {
Copy link
Contributor Author

@emcfarlane emcfarlane Apr 17, 2024

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.

Copy link
Contributor

@akshayjshah akshayjshah left a 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!

@emcfarlane emcfarlane merged commit fd9d60a into main Apr 17, 2024
@emcfarlane emcfarlane deleted the ed/fixMultiHeaderWrite branch April 17, 2024 20:18
@jhump jhump mentioned this pull request Apr 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants