(ctx context.Context, callHdr *CallHdr)
| 541 | } |
| 542 | |
| 543 | func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr) ([]hpack.HeaderField, error) { |
| 544 | aud := t.createAudience(callHdr) |
| 545 | ri := credentials.RequestInfo{ |
| 546 | Method: callHdr.Method, |
| 547 | AuthInfo: t.authInfo, |
| 548 | } |
| 549 | ctxWithRequestInfo := credentials.NewContextWithRequestInfo(ctx, ri) |
| 550 | authData, err := t.getTrAuthData(ctxWithRequestInfo, aud) |
| 551 | if err != nil { |
| 552 | return nil, err |
| 553 | } |
| 554 | callAuthData, err := t.getCallAuthData(ctxWithRequestInfo, aud, callHdr) |
| 555 | if err != nil { |
| 556 | return nil, err |
| 557 | } |
| 558 | // TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields |
| 559 | // first and create a slice of that exact size. |
| 560 | // Make the slice of certain predictable size to reduce allocations made by append. |
| 561 | hfLen := 7 // :method, :scheme, :path, :authority, content-type, user-agent, te |
| 562 | hfLen += len(authData) + len(callAuthData) |
| 563 | registeredCompressors := t.registeredCompressors |
| 564 | if callHdr.AcceptedCompressors != nil { |
| 565 | registeredCompressors = *callHdr.AcceptedCompressors |
| 566 | } |
| 567 | if callHdr.PreviousAttempts > 0 { |
| 568 | hfLen++ |
| 569 | } |
| 570 | if callHdr.SendCompress != "" { |
| 571 | hfLen++ |
| 572 | } |
| 573 | if registeredCompressors != "" { |
| 574 | hfLen++ |
| 575 | } |
| 576 | if _, ok := ctx.Deadline(); ok { |
| 577 | hfLen++ |
| 578 | } |
| 579 | headerFields := make([]hpack.HeaderField, 0, hfLen) |
| 580 | headerFields = append(headerFields, hpack.HeaderField{Name: ":method", Value: "POST"}) |
| 581 | headerFields = append(headerFields, hpack.HeaderField{Name: ":scheme", Value: t.scheme}) |
| 582 | headerFields = append(headerFields, hpack.HeaderField{Name: ":path", Value: callHdr.Method}) |
| 583 | headerFields = append(headerFields, hpack.HeaderField{Name: ":authority", Value: callHdr.Host}) |
| 584 | headerFields = append(headerFields, hpack.HeaderField{Name: "content-type", Value: grpcutil.ContentType(callHdr.ContentSubtype)}) |
| 585 | headerFields = append(headerFields, hpack.HeaderField{Name: "user-agent", Value: t.userAgent}) |
| 586 | headerFields = append(headerFields, hpack.HeaderField{Name: "te", Value: "trailers"}) |
| 587 | if callHdr.PreviousAttempts > 0 { |
| 588 | headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-previous-rpc-attempts", Value: strconv.Itoa(callHdr.PreviousAttempts)}) |
| 589 | } |
| 590 | |
| 591 | if callHdr.SendCompress != "" { |
| 592 | headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-encoding", Value: callHdr.SendCompress}) |
| 593 | // Include the outgoing compressor name when compressor is not registered |
| 594 | // via encoding.RegisterCompressor. This is possible when client uses |
| 595 | // WithCompressor dial option. |
| 596 | if !grpcutil.IsCompressorNameRegistered(callHdr.SendCompress) { |
| 597 | if registeredCompressors != "" { |
| 598 | registeredCompressors += "," |
| 599 | } |
| 600 | registeredCompressors += callHdr.SendCompress |
no test coverage detected