metadata: write original md before appended md (#2879)

This commit is contained in:
Yongzheng Lai 2019-06-26 01:34:12 +08:00 committed by Menghan Li
parent 70e8b38052
commit 7472edcc1e
2 changed files with 46 additions and 9 deletions

View File

@ -441,6 +441,15 @@ func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr)
if md, added, ok := metadata.FromOutgoingContextRaw(ctx); ok {
var k string
for k, vv := range md {
// HTTP doesn't allow you to set pseudoheaders after non pseudoheaders were set.
if isReservedHeader(k) {
continue
}
for _, v := range vv {
headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
}
}
for _, vv := range added {
for i, v := range vv {
if i%2 == 0 {
@ -454,15 +463,6 @@ func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr)
headerFields = append(headerFields, hpack.HeaderField{Name: strings.ToLower(k), Value: encodeMetadataHeader(k, v)})
}
}
for k, vv := range md {
// HTTP doesn't allow you to set pseudoheaders after non pseudoheaders were set.
if isReservedHeader(k) {
continue
}
for _, v := range vv {
headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
}
}
}
if md, ok := t.md.(*metadata.MD); ok {
for k, vv := range *md {

View File

@ -3146,6 +3146,43 @@ func testMetadataUnaryRPC(t *testing.T, e env) {
}
}
func (s) TestMetadataOrderUnaryRPC(t *testing.T) {
for _, e := range listTestEnv() {
testMetadataOrderUnaryRPC(t, e)
}
}
func testMetadataOrderUnaryRPC(t *testing.T, e env) {
te := newTest(t, e)
te.startServer(&testServer{security: e.security})
defer te.tearDown()
tc := testpb.NewTestServiceClient(te.clientConn())
ctx := metadata.NewOutgoingContext(context.Background(), testMetadata)
ctx = metadata.AppendToOutgoingContext(ctx, "key1", "value2")
ctx = metadata.AppendToOutgoingContext(ctx, "key1", "value3")
// using Join to built expected metadata instead of FromOutgoingContext
newMetadata := metadata.Join(testMetadata, metadata.Pairs("key1", "value2", "key1", "value3"))
var header metadata.MD
if _, err := tc.UnaryCall(ctx, &testpb.SimpleRequest{}, grpc.Header(&header)); err != nil {
t.Fatal(err)
}
// Ignore optional response headers that Servers may set:
if header != nil {
delete(header, "trailer") // RFC 2616 says server SHOULD (but optional) declare trailers
delete(header, "date") // the Date header is also optional
delete(header, "user-agent")
delete(header, "content-type")
}
if !reflect.DeepEqual(header, newMetadata) {
t.Fatalf("Received header metadata %v, want %v", header, newMetadata)
}
}
func (s) TestMultipleSetTrailerUnaryRPC(t *testing.T) {
for _, e := range listTestEnv() {
testMultipleSetTrailerUnaryRPC(t, e)