diff --git a/runtime/handler.go b/runtime/handler.go index 8fe6a77efd5..63dc812b781 100644 --- a/runtime/handler.go +++ b/runtime/handler.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "net/textproto" + "strconv" "strings" "google.golang.org/genproto/googleapis/api/httpbody" @@ -176,6 +177,10 @@ func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marsha return } + if !doForwardTrailers { + w.Header().Set("Content-Length", strconv.Itoa(len(buf))) + } + if _, err = w.Write(buf); err != nil { grpclog.Infof("Failed to write response: %v", err) } diff --git a/runtime/handler_test.go b/runtime/handler_test.go index 88f4a92a5b4..b0ad6e2c90d 100644 --- a/runtime/handler_test.go +++ b/runtime/handler_test.go @@ -339,6 +339,7 @@ func TestOutgoingHeaderMatcher(t *testing.T) { ), }, headers: http.Header{ + "Content-Length": []string{"12"}, "Content-Type": []string{"application/json"}, "Grpc-Metadata-Foo": []string{"bar"}, "Grpc-Metadata-Baz": []string{"qux"}, @@ -353,8 +354,9 @@ func TestOutgoingHeaderMatcher(t *testing.T) { ), }, headers: http.Header{ - "Content-Type": []string{"application/json"}, - "Custom-Foo": []string{"bar"}, + "Content-Length": []string{"12"}, + "Content-Type": []string{"application/json"}, + "Custom-Foo": []string{"bar"}, }, matcher: func(key string) (string, bool) { switch key { @@ -412,8 +414,9 @@ func TestOutgoingTrailerMatcher(t *testing.T) { "Te": []string{"trailers"}, }, headers: http.Header{ - "Content-Type": []string{"application/json"}, - "Trailer": []string{"Grpc-Trailer-Foo,Grpc-Trailer-Baz"}, + "Transfer-Encoding": []string{"chunked"}, + "Content-Type": []string{"application/json"}, + "Trailer": []string{"Grpc-Trailer-Foo", "Grpc-Trailer-Baz"}, }, trailer: http.Header{ "Grpc-Trailer-Foo": []string{"bar"}, @@ -429,7 +432,8 @@ func TestOutgoingTrailerMatcher(t *testing.T) { ), }, headers: http.Header{ - "Content-Type": []string{"application/json"}, + "Content-Length": []string{"12"}, + "Content-Type": []string{"application/json"}, }, }, { @@ -444,8 +448,9 @@ func TestOutgoingTrailerMatcher(t *testing.T) { "Te": []string{"trailers"}, }, headers: http.Header{ - "Content-Type": []string{"application/json"}, - "Trailer": []string{"Custom-Trailer-Foo"}, + "Transfer-Encoding": []string{"chunked"}, + "Content-Type": []string{"application/json"}, + "Trailer": []string{"Custom-Trailer-Foo"}, }, trailer: http.Header{ "Custom-Trailer-Foo": []string{"bar"}, @@ -478,6 +483,10 @@ func TestOutgoingTrailerMatcher(t *testing.T) { t.Fatalf("StatusCode %d want %d", w.StatusCode, http.StatusOK) } + if !reflect.DeepEqual(w.Header, tc.headers) { + t.Fatalf("Header %v want %v", w.Header, tc.headers) + } + if !reflect.DeepEqual(w.Trailer, tc.trailer) { t.Fatalf("Trailer %v want %v", w.Trailer, tc.trailer) }