diff --git a/transport/http_util.go b/transport/http_util.go index f1233fa48..251731184 100644 --- a/transport/http_util.go +++ b/transport/http_util.go @@ -120,7 +120,7 @@ type headerFrame interface { // reserved by gRPC protocol. Any other headers are classified as the // user-specified metadata. func isReservedHeader(hdr string) bool { - if hdr[0] == ':' { + if hdr != "" && hdr[0] == ':' { return true } switch hdr { diff --git a/transport/transport_test.go b/transport/transport_test.go index 4b50f7367..07128d5db 100644 --- a/transport/transport_test.go +++ b/transport/transport_test.go @@ -660,3 +660,26 @@ func TestStreamContext(t *testing.T) { t.Fatalf("GetStreamFromContext(%v) = %v, %t, want: %v, true", ctx, *s, ok, expectedStream) } } + +func TestIsReservedHeader(t *testing.T) { + tests := []struct { + h string + want bool + }{ + {"", false}, // but should be rejected earlier + {"foo", false}, + {"content-type", true}, + {"grpc-message-type", true}, + {"grpc-encoding", true}, + {"grpc-message", true}, + {"grpc-status", true}, + {"grpc-timeout", true}, + {"te", true}, + } + for _, tt := range tests { + got := isReservedHeader(tt.h) + if got != tt.want { + t.Errorf("isReservedHeader(%q) = %v; want %v", tt.h, got, tt.want) + } + } +}