Skip to content

Commit 9c920c8

Browse files
committed
addressing review comments
1 parent aceb8be commit 9c920c8

File tree

2 files changed

+56
-24
lines changed

2 files changed

+56
-24
lines changed

internal/transport/http2_client.go

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,10 +1466,11 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
14661466
grpcMessage string
14671467
recvCompress string
14681468
httpStatusErr string
1469-
rawStatusCode = codes.Internal
1469+
// the code from the grpc-status header, if present
1470+
grpcStatusCode = codes.Internal
14701471
// headerError is set if an error is encountered while parsing the headers
1471-
headerError string
1472-
receivedHTTPStatus string
1472+
headerError string
1473+
httpStatus string
14731474
)
14741475

14751476
for _, hf := range frame.Fields {
@@ -1491,13 +1492,11 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
14911492
t.closeStream(s, se.Err(), true, http2.ErrCodeProtocol, se, nil, endStream)
14921493
return
14931494
}
1494-
rawStatusCode = codes.Code(uint32(code))
1495+
grpcStatusCode = codes.Code(uint32(code))
14951496
case "grpc-message":
14961497
grpcMessage = decodeGrpcMessage(hf.Value)
14971498
case ":status":
1498-
if !isGRPC {
1499-
receivedHTTPStatus = hf.Value
1500-
}
1499+
httpStatus = hf.Value
15011500
default:
15021501
if isReservedHeader(hf.Name) && !isWhitelistedHeader(hf.Name) {
15031502
break
@@ -1512,18 +1511,18 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
15121511
}
15131512
}
15141513

1515-
// If a non gRPC response is received, then evaluate entire http status and process close stream / response.
1516-
// In case http status doesn't provide any error information (status : 200), evalute response code to be Unknown.
1514+
// If a non gRPC response is received, then evaluate entire http status and
1515+
// process close stream / response.
1516+
// In case http status doesn't provide any error information (status : 200),
1517+
// evalute response code to be Unknown.
15171518
if !isGRPC {
1518-
var grpcErrorCode = codes.Internal // when header does not include HTTP status, return INTERNAL
1519-
var errs []string
1520-
1521-
switch receivedHTTPStatus {
1519+
var grpcErrorCode = codes.Internal
1520+
switch httpStatus {
15221521
case "":
15231522
httpStatusErr = "malformed header: missing HTTP status"
15241523
default:
15251524
// Any other status code (e.g., "404", "503"). We must parse it.
1526-
c, err := strconv.ParseInt(receivedHTTPStatus, 10, 32)
1525+
c, err := strconv.ParseInt(httpStatus, 10, 32)
15271526
if err != nil {
15281527
se := status.New(grpcErrorCode, fmt.Sprintf("transport: malformed http-status: %v", err))
15291528
t.closeStream(s, se.Err(), true, http2.ErrCodeProtocol, se, nil, endStream)
@@ -1536,7 +1535,7 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
15361535
"protocol error: informational header with status code %d must not have END_STREAM set", statusCode))
15371536
t.closeStream(s, se.Err(), true, http2.ErrCodeProtocol, se, nil, endStream)
15381537
}
1539-
//In case of informational headers return
1538+
// In case of informational headers return
15401539
return
15411540
}
15421541
httpStatusErr = fmt.Sprintf(
@@ -1550,7 +1549,7 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
15501549
grpcErrorCode = codes.Unknown
15511550
}
15521551
}
1553-
1552+
var errs []string
15541553
if httpStatusErr != "" {
15551554
errs = append(errs, httpStatusErr)
15561555
}
@@ -1613,7 +1612,7 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
16131612
return
16141613
}
16151614

1616-
status := istatus.NewWithProto(rawStatusCode, grpcMessage, mdata[grpcStatusDetailsBinHeader])
1615+
status := istatus.NewWithProto(grpcStatusCode, grpcMessage, mdata[grpcStatusDetailsBinHeader])
16171616

16181617
// If client received END_STREAM from server while stream was still active,
16191618
// send RST_STREAM.

internal/transport/transport_test.go

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,7 +2588,7 @@ func (s) TestClientHandshakeInfoDialer(t *testing.T) {
25882588
}
25892589
}
25902590

2591-
func (s) TestClientDecodeHeaderStatusErr(t *testing.T) {
2591+
func TestClientDecodeHeaderStatusErr(t *testing.T) {
25922592
testStream := func() *ClientStream {
25932593
return &ClientStream{
25942594
Stream: &Stream{
@@ -2620,6 +2620,8 @@ func (s) TestClientDecodeHeaderStatusErr(t *testing.T) {
26202620
wantStatus *status.Status
26212621
// end stream output
26222622
wantStatusEndStream *status.Status
2623+
// head channel closed
2624+
headerChanClosedForEndStream bool
26232625
}{
26242626
{
26252627
name: "valid header",
@@ -2644,11 +2646,14 @@ func (s) TestClientDecodeHeaderStatusErr(t *testing.T) {
26442646
},
26452647
wantStatus: status.New(
26462648
codes.Unknown,
2647-
"malformed header: missing HTTP content-type",
2649+
"unexpected HTTP status code received from server: 200 (OK); malformed header: missing HTTP content-type",
26482650
),
2651+
headerChanClosedForEndStream: true,
2652+
// when headerChan is closed, it is already gRPC and we just need
2653+
// grpc-status
26492654
wantStatusEndStream: status.New(
2650-
codes.Unknown,
2651-
"malformed header: missing HTTP content-type",
2655+
codes.OK,
2656+
"",
26522657
),
26532658
},
26542659
{
@@ -2680,11 +2685,32 @@ func (s) TestClientDecodeHeaderStatusErr(t *testing.T) {
26802685
codes.Internal,
26812686
"malformed header: missing HTTP status; transport: received unexpected content-type \"application/json\"",
26822687
),
2688+
// This content type will only come when end stream is also initial
2689+
// header, otherwise we would already be talking gRPC
26832690
wantStatusEndStream: status.New(
26842691
codes.Internal,
26852692
"malformed header: missing HTTP status; transport: received unexpected content-type \"application/json\"",
26862693
),
26872694
},
2695+
{
2696+
name: "invalid http content type with http status 504 translation",
2697+
metaHeaderFrame: &http2.MetaHeadersFrame{
2698+
Fields: []hpack.HeaderField{
2699+
{Name: "content-type", Value: "application/json"},
2700+
{Name: ":status", Value: "504"},
2701+
},
2702+
},
2703+
wantStatus: status.New(
2704+
codes.Unavailable,
2705+
"unexpected HTTP status code received from server: 504 (Gateway Timeout); transport: received unexpected content-type \"application/json\"",
2706+
),
2707+
// This content type will only come when end stream is also initial
2708+
// header, otherwise we would already be talking gRPC
2709+
wantStatusEndStream: status.New(
2710+
codes.Unavailable,
2711+
"unexpected HTTP status code received from server: 504 (Gateway Timeout); transport: received unexpected content-type \"application/json\"",
2712+
),
2713+
},
26882714
{
26892715
name: "http fallback and invalid http status",
26902716
metaHeaderFrame: &http2.MetaHeadersFrame{
@@ -2697,9 +2723,12 @@ func (s) TestClientDecodeHeaderStatusErr(t *testing.T) {
26972723
codes.Internal,
26982724
"transport: malformed http-status: strconv.ParseInt: parsing \"xxxx\": invalid syntax",
26992725
),
2726+
// for end stream, when we are already talking gRPC, we expect
2727+
// grpc - status and fail for it, we will ignore http status.
2728+
headerChanClosedForEndStream: true,
27002729
wantStatusEndStream: status.New(
27012730
codes.Internal,
2702-
"transport: malformed http-status: strconv.ParseInt: parsing \"xxxx\": invalid syntax",
2731+
"",
27032732
),
27042733
},
27052734
{
@@ -2747,8 +2776,9 @@ func (s) TestClientDecodeHeaderStatusErr(t *testing.T) {
27472776
{Name: ":status", Value: "504"},
27482777
},
27492778
},
2750-
wantStatus: status.New(codes.OK, ""),
2751-
wantStatusEndStream: status.New(codes.Internal, ""),
2779+
wantStatus: status.New(codes.OK, ""),
2780+
headerChanClosedForEndStream: true,
2781+
wantStatusEndStream: status.New(codes.Internal, ""),
27522782
},
27532783
{
27542784
name: "ignore valid http status for grpc",
@@ -2797,6 +2827,9 @@ func (s) TestClientDecodeHeaderStatusErr(t *testing.T) {
27972827
})
27982828
t.Run(fmt.Sprintf("%s-end_stream", test.name), func(t *testing.T) {
27992829
ts := testStream()
2830+
if test.headerChanClosedForEndStream {
2831+
ts.headerChanClosed = 1
2832+
}
28002833
s := testClient(ts)
28012834

28022835
test.metaHeaderFrame.HeadersFrame = &http2.HeadersFrame{

0 commit comments

Comments
 (0)