@@ -1480,17 +1480,14 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
1480
1480
contentTypeErr = "malformed header: missing HTTP content-type"
1481
1481
grpcMessage string
1482
1482
recvCompress string
1483
- httpStatusCode * int
1484
1483
httpStatusErr string
1485
- rawStatusCode = codes .Unknown
1484
+ // the code from the grpc-status header, if present
1485
+ grpcStatusCode = codes .Internal
1486
1486
// headerError is set if an error is encountered while parsing the headers
1487
1487
headerError string
1488
+ httpStatus string
1488
1489
)
1489
1490
1490
- if initialHeader {
1491
- httpStatusErr = "malformed header: missing HTTP status"
1492
- }
1493
-
1494
1491
for _ , hf := range frame .Fields {
1495
1492
switch hf .Name {
1496
1493
case "content-type" :
@@ -1510,69 +1507,71 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
1510
1507
t .closeStream (s , se .Err (), true , http2 .ErrCodeProtocol , se , nil , endStream )
1511
1508
return
1512
1509
}
1513
- rawStatusCode = codes .Code (uint32 (code ))
1510
+ grpcStatusCode = codes .Code (uint32 (code ))
1514
1511
case "grpc-message" :
1515
1512
grpcMessage = decodeGrpcMessage (hf .Value )
1516
1513
case ":status" :
1517
- c , err := strconv .ParseInt (hf .Value , 10 , 32 )
1514
+ httpStatus = hf .Value
1515
+ default :
1516
+ if isReservedHeader (hf .Name ) && ! isWhitelistedHeader (hf .Name ) {
1517
+ break
1518
+ }
1519
+ v , err := decodeMetadataHeader (hf .Name , hf .Value )
1518
1520
if err != nil {
1519
- se := status .New (codes .Internal , fmt .Sprintf ("transport: malformed http-status: %v" , err ))
1521
+ headerError = fmt .Sprintf ("transport: malformed %s: %v" , hf .Name , err )
1522
+ logger .Warningf ("Failed to decode metadata header (%q, %q): %v" , hf .Name , hf .Value , err )
1523
+ break
1524
+ }
1525
+ mdata [hf .Name ] = append (mdata [hf .Name ], v )
1526
+ }
1527
+ }
1528
+
1529
+ // If a non-gRPC response is received, then evaluate the HTTP status to
1530
+ // process the response and close the stream.
1531
+ // In case http status doesn't provide any error information (status : 200),
1532
+ // then evalute response code to be Unknown.
1533
+ if ! isGRPC {
1534
+ var grpcErrorCode = codes .Internal
1535
+ if httpStatus == "" {
1536
+ httpStatusErr = "malformed header: missing HTTP status"
1537
+ } else {
1538
+ // Parse the status codes (e.g. "200", 404").
1539
+ statusCode , err := strconv .Atoi (httpStatus )
1540
+ if err != nil {
1541
+ se := status .New (grpcErrorCode , fmt .Sprintf ("transport: malformed http-status: %v" , err ))
1520
1542
t .closeStream (s , se .Err (), true , http2 .ErrCodeProtocol , se , nil , endStream )
1521
1543
return
1522
1544
}
1523
- statusCode := int (c )
1524
1545
if statusCode >= 100 && statusCode < 200 {
1525
1546
if endStream {
1526
1547
se := status .New (codes .Internal , fmt .Sprintf (
1527
1548
"protocol error: informational header with status code %d must not have END_STREAM set" , statusCode ))
1528
1549
t .closeStream (s , se .Err (), true , http2 .ErrCodeProtocol , se , nil , endStream )
1529
1550
}
1551
+ // In case of informational headers, return.
1530
1552
return
1531
1553
}
1532
- httpStatusCode = & statusCode
1533
- if statusCode == 200 {
1534
- httpStatusErr = ""
1535
- break
1536
- }
1537
-
1538
1554
httpStatusErr = fmt .Sprintf (
1539
1555
"unexpected HTTP status code received from server: %d (%s)" ,
1540
1556
statusCode ,
1541
1557
http .StatusText (statusCode ),
1542
1558
)
1543
- default :
1544
- if isReservedHeader (hf .Name ) && ! isWhitelistedHeader (hf .Name ) {
1545
- break
1546
- }
1547
- v , err := decodeMetadataHeader (hf .Name , hf .Value )
1548
- if err != nil {
1549
- headerError = fmt .Sprintf ("transport: malformed %s: %v" , hf .Name , err )
1550
- logger .Warningf ("Failed to decode metadata header (%q, %q): %v" , hf .Name , hf .Value , err )
1551
- break
1552
- }
1553
- mdata [hf .Name ] = append (mdata [hf .Name ], v )
1554
- }
1555
- }
1556
-
1557
- if ! isGRPC || httpStatusErr != "" {
1558
- var code = codes .Internal // when header does not include HTTP status, return INTERNAL
1559
-
1560
- if httpStatusCode != nil {
1561
1559
var ok bool
1562
- code , ok = HTTPStatusConvTab [* httpStatusCode ]
1560
+ grpcErrorCode , ok = HTTPStatusConvTab [statusCode ]
1563
1561
if ! ok {
1564
- code = codes .Unknown
1562
+ grpcErrorCode = codes .Unknown
1565
1563
}
1566
1564
}
1567
1565
var errs []string
1568
1566
if httpStatusErr != "" {
1569
1567
errs = append (errs , httpStatusErr )
1570
1568
}
1569
+
1571
1570
if contentTypeErr != "" {
1572
1571
errs = append (errs , contentTypeErr )
1573
1572
}
1574
- // Verify the HTTP response is a 200.
1575
- se := status .New (code , strings .Join (errs , "; " ))
1573
+
1574
+ se := status .New (grpcErrorCode , strings .Join (errs , "; " ))
1576
1575
t .closeStream (s , se .Err (), true , http2 .ErrCodeProtocol , se , nil , endStream )
1577
1576
return
1578
1577
}
@@ -1626,7 +1625,7 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
1626
1625
return
1627
1626
}
1628
1627
1629
- status := istatus .NewWithProto (rawStatusCode , grpcMessage , mdata [grpcStatusDetailsBinHeader ])
1628
+ status := istatus .NewWithProto (grpcStatusCode , grpcMessage , mdata [grpcStatusDetailsBinHeader ])
1630
1629
1631
1630
// If client received END_STREAM from server while stream was still active,
1632
1631
// send RST_STREAM.
0 commit comments