operateHeaders takes action on the decoded headers.
(frame *http2.MetaHeadersFrame)
| 1469 | |
| 1470 | // operateHeaders takes action on the decoded headers. |
| 1471 | func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) { |
| 1472 | s := t.getStream(frame) |
| 1473 | if s == nil { |
| 1474 | return |
| 1475 | } |
| 1476 | endStream := frame.StreamEnded() |
| 1477 | s.bytesReceived.Store(true) |
| 1478 | initialHeader := atomic.LoadUint32(&s.headerChanClosed) == 0 |
| 1479 | |
| 1480 | if !initialHeader && !endStream { |
| 1481 | // As specified by gRPC over HTTP2, a HEADERS frame (and associated CONTINUATION frames) can only appear at the start or end of a stream. Therefore, second HEADERS frame must have EOS bit set. |
| 1482 | st := status.New(codes.Internal, "a HEADERS frame cannot appear in the middle of a stream") |
| 1483 | t.closeStream(s, st.Err(), true, http2.ErrCodeProtocol, st, nil, false) |
| 1484 | return |
| 1485 | } |
| 1486 | |
| 1487 | // frame.Truncated is set to true when framer detects that the current header |
| 1488 | // list size hits MaxHeaderListSize limit. |
| 1489 | if frame.Truncated { |
| 1490 | se := status.New(codes.Internal, "peer header list size exceeded limit") |
| 1491 | t.closeStream(s, se.Err(), true, http2.ErrCodeFrameSize, se, nil, endStream) |
| 1492 | return |
| 1493 | } |
| 1494 | |
| 1495 | // If we are collecting non-gRPC response data and receive a trailing |
| 1496 | // HEADERS frame with END_STREAM, finalize the buffered data and close |
| 1497 | // the stream. |
| 1498 | if s.nonGRPCStatus != nil { |
| 1499 | if endStream { |
| 1500 | st := s.finalizeNonGRPCStatus() |
| 1501 | t.closeStream(s, st.Err(), true, http2.ErrCodeProtocol, st, nil, true) |
| 1502 | } |
| 1503 | return |
| 1504 | } |
| 1505 | |
| 1506 | var ( |
| 1507 | // If a gRPC Response-Headers has already been received, then it means |
| 1508 | // that the peer is speaking gRPC and we are in gRPC mode. |
| 1509 | isGRPC = !initialHeader |
| 1510 | mdata = make(map[string][]string) |
| 1511 | contentTypeErr = "malformed header: missing HTTP content-type" |
| 1512 | grpcMessage string |
| 1513 | recvCompress string |
| 1514 | httpStatusErr string |
| 1515 | // the code from the grpc-status header, if present |
| 1516 | grpcStatusCode = codes.Unknown |
| 1517 | // headerError is set if an error is encountered while parsing the headers |
| 1518 | headerError string |
| 1519 | httpStatus string |
| 1520 | ) |
| 1521 | |
| 1522 | for _, hf := range frame.Fields { |
| 1523 | switch hf.Name { |
| 1524 | case "content-type": |
| 1525 | if _, validContentType := grpcutil.ContentSubtype(hf.Value); !validContentType { |
| 1526 | contentTypeErr = fmt.Sprintf("transport: received unexpected content-type %q", hf.Value) |
| 1527 | break |
| 1528 | } |
no test coverage detected