-
Notifications
You must be signed in to change notification settings - Fork 4.6k
client: ignore http status header for gRPC streams #8548
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?
client: ignore http status header for gRPC streams #8548
Conversation
Fixes grpc#8486 When a gRPC response is received with content type application/grpc, we then do not expect any information in the http status and the status information needs to be conveyed by gRPC status only. In case of missing gRPC status, we will throw an Internal error instead of Unknown in accordance with https://grpc.io/docs/guides/status-codes/ Changes : - Ignore http status in case of content type application/grpc - Change the default rawStatusCode to return Internal for missing grpc status RELEASE NOTES: * client : Ignore http status for gRPC mode and return Internal error for missing grpc status
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #8548 +/- ##
==========================================
+ Coverage 81.64% 82.02% +0.37%
==========================================
Files 413 415 +2
Lines 40621 40684 +63
==========================================
+ Hits 33167 33370 +203
+ Misses 5991 5923 -68
+ Partials 1463 1391 -72
🚀 New features to boost your workflow:
|
In the grpc-go repo, we use the assignee to indicate who the review is pending on (author or reviewer). We ignore the reviewer status (the yellow pending re-review dot). Assigning to myself. |
For the PR title, we add the name of the Go package (e.g. |
e1f6dbc
to
f123124
Compare
…rpc-content-type-8486
f123124
to
b4cce55
Compare
internal/transport/http2_client.go
Outdated
// headerError is set if an error is encountered while parsing the headers | ||
headerError string | ||
headerError string | ||
receivedHTTPStatus string |
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.
nit: We can omit the received
prefix int the variable name, shortening it to httpStatus
since it doesn't effect readability.
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.
Ping on this.
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.
+1
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.
done.
internal/transport/http2_client.go
Outdated
case "200": | ||
grpcErrorCode = codes.Unknown |
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.
Is this explicit check required? Since 200 isn't present in the HTTPStatusConvTab
map, I think it may be omitted.
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.
The idea is when no error information can be derived from http status since it is 200, we can simply return Unknown code.
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.
The default
case also adds a error message which seems useful. I think we should remove the special case unless it requires different handling in code. We don't need to worry too much about optimizing the error case, since they're expected to be infrequent.
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.
+1; please remove special cases when possible most of the time. Less code = easier to understand code.
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.
done.
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.
done.
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.
Mostly LGTM, left a few minor comments.
internal/transport/http2_client.go
Outdated
case "200": | ||
grpcErrorCode = codes.Unknown |
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.
The default
case also adds a error message which seems useful. I think we should remove the special case unless it requires different handling in code. We don't need to worry too much about optimizing the error case, since they're expected to be infrequent.
internal/transport/http2_client.go
Outdated
// headerError is set if an error is encountered while parsing the headers | ||
headerError string | ||
headerError string | ||
receivedHTTPStatus string |
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.
Ping on this.
internal/transport/http2_client.go
Outdated
"protocol error: informational header with status code %d must not have END_STREAM set", statusCode)) | ||
t.closeStream(s, se.Err(), true, http2.ErrCodeProtocol, se, nil, endStream) | ||
} | ||
//In case of informational headers return |
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.
nit: Need a space at the beginning of the comment here.
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.
+1
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.
done.
internal/transport/http2_client.go
Outdated
httpStatusCode *int | ||
httpStatusErr string | ||
rawStatusCode = codes.Unknown | ||
rawStatusCode = codes.Internal |
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 name isn't a good one, I think. Maybe call this grpcStatusCode
and add a comment?
rawStatusCode = codes.Internal | |
grpcStatusCode = codes.Internal // the code from the grpc-status header, if present |
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.
done.
internal/transport/http2_client.go
Outdated
// headerError is set if an error is encountered while parsing the headers | ||
headerError string | ||
headerError string | ||
receivedHTTPStatus string |
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.
+1
internal/transport/http2_client.go
Outdated
case "200": | ||
grpcErrorCode = codes.Unknown |
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.
+1; please remove special cases when possible most of the time. Less code = easier to understand code.
internal/transport/http2_client.go
Outdated
grpcMessage = decodeGrpcMessage(hf.Value) | ||
case ":status": | ||
c, err := strconv.ParseInt(hf.Value, 10, 32) | ||
if !isGRPC { |
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 is making the assumption that :status
appears after content-type
, which AFAIK is not required. That's why the code before does header processing by setting a bunch of locals and then looking at them later.
In this case it's not going to cause any problems, since we don't look at this variable if isGRPC
is true
, but I think it's better to remove it. And it's not even necessarily a performance win, since conditional branches are potentially worse for performance than setting a Go string (which is not a full copy of the string itself).
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.
thanks for the explanation, thats a great catch! - done.
internal/transport/http2_client.go
Outdated
// If a non gRPC response is received, then evaluate entire http status and process close stream / response. | ||
// In case http status doesn't provide any error information (status : 200), evalute response code to be Unknown. |
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.
Please wrap comments to 80 columns.
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.
done.
internal/transport/http2_client.go
Outdated
// In case http status doesn't provide any error information (status : 200), evalute response code to be Unknown. | ||
if !isGRPC { | ||
var grpcErrorCode = codes.Internal // when header does not include HTTP status, return INTERNAL | ||
var errs []string |
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.
Please move this back to where it was defined before; i.e. as late as possible.
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.
done.
internal/transport/http2_client.go
Outdated
"protocol error: informational header with status code %d must not have END_STREAM set", statusCode)) | ||
t.closeStream(s, se.Err(), true, http2.ErrCodeProtocol, se, nil, endStream) | ||
} | ||
//In case of informational headers return |
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.
+1
9c920c8
to
734cd4d
Compare
Fixes #8486
When a gRPC response is received with content type application/grpc, we then do not expect any information in the http status and the status information needs to be conveyed by gRPC status only.
In case of missing gRPC status, we will throw an Internal error instead of Unknown in accordance with https://grpc.io/docs/guides/status-codes/
RELEASE NOTES: