Repository: grpc/grpc-go
File: internal/transport/http2_server.go (Go)

Code before:
	}
}

func (t *http2Server) handleWindowUpdate(f *http2.WindowUpdateFrame) {
	t.controlBuf.put(&incomingWindowUpdate{
		streamID:  f.Header().StreamID,
		increment: f.Increment,
	})
}

func appendHeaderFieldsFromMD(headerFields []hpack.HeaderField, md metadata.MD) []hpack.HeaderField {
	for k, vv := range md {
		if isReservedHeader(k) {
			// Clients don't tolerate reading restricted headers after some non restricted ones were sent.
			continue
		}
		for _, v := range vv {
			headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
		}
	}
	return headerFields
}

// checkForHeaderListSize checks if the header list size exceeds the limit set
// by the peer. It returns false if the limit is exceeded.
func checkForHeaderListSize(hf []hpack.HeaderField, maxSendHeaderListSize *uint32) bool {
	if maxSendHeaderListSize == nil {
		return true
	}
	var sz int64
	for _, f := range hf {
		if sz += int64(f.Size()); sz > int64(*maxSendHeaderListSize) {
			return false
		}
	}
	return true
}

func (t *http2Server) checkForHeaderListSize(it any) bool {
	hdrFrame := it.(*headerFrame)
	if !checkForHeaderListSize(hdrFrame.hf, t.maxSendHeaderListSize) {
		if t.logger.V(logLevel) {
			t.logger.Infof("Header list size to send violates the maximum size (%d bytes) set by client", *t.maxSendHeaderListSize)
		}
		return false
	}
	return true
}

// buildEarlyAbortHF builds the header fields for an early abort response.
func buildEarlyAbortHF(httpStatus uint32, contentSubtype string, stat *status.Status) []hpack.HeaderField {

Review comment (suggestion):
Instead of adding a new function that accepts a `[]hpack.HeaderField`, can the existing method be updated to `func (t *http2Server) checkForHeaderListSize(hf []hpack.HeaderField) bool`?

That should make diff smaller.

Code after:
		t.controlBuf.put(&goAway{code: http2.ErrCodeEnhanceYourCalm, debugData: []byte("too_many_pings"), closeConn: errors.New("got too many pings from the client")})
	}
}

func (t *http2Server) handleWindowUpdate(f *http2.WindowUpdateFrame) {
	t.controlBuf.put(&incomingWindowUpdate{
		streamID:  f.Header().StreamID,
		increment: f.Increment,
	})
}

func appendHeaderFieldsFromMD(headerFields []hpack.HeaderField, md metadata.MD) []hpack.HeaderField {
	for k, vv := range md {
		if isReservedHeader(k) {
			// Clients don't tolerate reading restricted headers after some non restricted ones were sent.
			continue
		}
		for _, v := range vv {
			headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
		}
	}
	return headerFields
}

func (t *http2Server) checkForHeaderListSize(hf []hpack.HeaderField) bool {
	if t.maxSendHeaderListSize == nil {
		return true
	}
	var sz int64
	for _, f := range hf {
		if sz += int64(f.Size()); sz > int64(*t.maxSendHeaderListSize) {
			if t.logger.V(logLevel) {
				t.logger.Infof("Header list size to send violates the maximum size (%d bytes) set by client", *t.maxSendHeaderListSize)
			}
			return false
		}
	}
	return true
}

// writeEarlyAbort sends an early abort response with the given HTTP status and
// gRPC status. If the header list size exceeds the peer's limit, it sends a
// RST_STREAM instead.
func (t *http2Server) writeEarlyAbort(streamID uint32, contentSubtype string, stat *status.Status, httpStatus uint32, rst bool) {
	hf := []hpack.HeaderField{
		{Name: ":status", Value: strconv.Itoa(int(httpStatus))},
		{Name: "content-type", Value: grpcutil.ContentType(contentSubtype)},
		{Name: "grpc-status", Value: strconv.Itoa(int(stat.Code()))},
		{Name: "grpc-message", Value: encodeGrpcMessage(stat.Message())},
	}
	if p := istatus.RawStatusProto(stat); len(p.GetDetails()) > 0 {