@@ -1480,17 +1480,14 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
14801480 contentTypeErr = "malformed header: missing HTTP content-type"
14811481 grpcMessage string
14821482 recvCompress string
1483- httpStatusCode * int
14841483 httpStatusErr string
1485- rawStatusCode = codes .Unknown
1484+ // the code from the grpc-status header, if present
1485+ grpcStatusCode = codes .Internal
14861486 // headerError is set if an error is encountered while parsing the headers
14871487 headerError string
1488+ httpStatus string
14881489 )
14891490
1490- if initialHeader {
1491- httpStatusErr = "malformed header: missing HTTP status"
1492- }
1493-
14941491 for _ , hf := range frame .Fields {
14951492 switch hf .Name {
14961493 case "content-type" :
@@ -1510,69 +1507,71 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
15101507 t .closeStream (s , se .Err (), true , http2 .ErrCodeProtocol , se , nil , endStream )
15111508 return
15121509 }
1513- rawStatusCode = codes .Code (uint32 (code ))
1510+ grpcStatusCode = codes .Code (uint32 (code ))
15141511 case "grpc-message" :
15151512 grpcMessage = decodeGrpcMessage (hf .Value )
15161513 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 )
15181520 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 ))
15201542 t .closeStream (s , se .Err (), true , http2 .ErrCodeProtocol , se , nil , endStream )
15211543 return
15221544 }
1523- statusCode := int (c )
15241545 if statusCode >= 100 && statusCode < 200 {
15251546 if endStream {
15261547 se := status .New (codes .Internal , fmt .Sprintf (
15271548 "protocol error: informational header with status code %d must not have END_STREAM set" , statusCode ))
15281549 t .closeStream (s , se .Err (), true , http2 .ErrCodeProtocol , se , nil , endStream )
15291550 }
1551+ // In case of informational headers, return.
15301552 return
15311553 }
1532- httpStatusCode = & statusCode
1533- if statusCode == 200 {
1534- httpStatusErr = ""
1535- break
1536- }
1537-
15381554 httpStatusErr = fmt .Sprintf (
15391555 "unexpected HTTP status code received from server: %d (%s)" ,
15401556 statusCode ,
15411557 http .StatusText (statusCode ),
15421558 )
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 {
15611559 var ok bool
1562- code , ok = HTTPStatusConvTab [* httpStatusCode ]
1560+ grpcErrorCode , ok = HTTPStatusConvTab [statusCode ]
15631561 if ! ok {
1564- code = codes .Unknown
1562+ grpcErrorCode = codes .Unknown
15651563 }
15661564 }
15671565 var errs []string
15681566 if httpStatusErr != "" {
15691567 errs = append (errs , httpStatusErr )
15701568 }
1569+
15711570 if contentTypeErr != "" {
15721571 errs = append (errs , contentTypeErr )
15731572 }
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 , "; " ))
15761575 t .closeStream (s , se .Err (), true , http2 .ErrCodeProtocol , se , nil , endStream )
15771576 return
15781577 }
@@ -1626,7 +1625,7 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
16261625 return
16271626 }
16281627
1629- status := istatus .NewWithProto (rawStatusCode , grpcMessage , mdata [grpcStatusDetailsBinHeader ])
1628+ status := istatus .NewWithProto (grpcStatusCode , grpcMessage , mdata [grpcStatusDetailsBinHeader ])
16301629
16311630 // If client received END_STREAM from server while stream was still active,
16321631 // send RST_STREAM.
0 commit comments