@@ -2307,6 +2307,97 @@ func TestStreamUnexpectedEOF(t *testing.T) {
23072307 }
23082308}
23092309
2310+ func TestTrailersOnlyErrors (t * testing.T ) {
2311+ t .Parallel ()
2312+
2313+ head := [3 ]byte {}
2314+ testcases := []struct {
2315+ name string
2316+ handler http.HandlerFunc
2317+ options []connect.ClientOption
2318+ expectCode connect.Code
2319+ expectMsg string
2320+ }{{
2321+ name : "grpc_body_after_trailers-only" ,
2322+ options : []connect.ClientOption {connect .WithGRPC ()},
2323+ handler : func (responseWriter http.ResponseWriter , _ * http.Request ) {
2324+ header := responseWriter .Header ()
2325+ header .Set ("Content-Type" , "application/grpc" )
2326+ header .Set ("Grpc-Status" , "3" )
2327+ _ , err := responseWriter .Write (head [:])
2328+ assert .Nil (t , err )
2329+ },
2330+ expectCode : connect .CodeInternal ,
2331+ expectMsg : fmt .Sprintf ("internal: corrupt response: %d extra bytes after trailers-only response" , len (head )),
2332+ }, {
2333+ name : "grpc-web_body_after_trailers-only" ,
2334+ options : []connect.ClientOption {connect .WithGRPCWeb ()},
2335+ handler : func (responseWriter http.ResponseWriter , _ * http.Request ) {
2336+ header := responseWriter .Header ()
2337+ header .Set ("Content-Type" , "application/grpc-web" )
2338+ header .Set ("Grpc-Status" , "3" )
2339+ _ , err := responseWriter .Write (head [:])
2340+ assert .Nil (t , err )
2341+ },
2342+ expectCode : connect .CodeInternal ,
2343+ expectMsg : fmt .Sprintf ("internal: corrupt response: %d extra bytes after trailers-only response" , len (head )),
2344+ }, {
2345+ name : "grpc_trailers_after_trailers-only" ,
2346+ options : []connect.ClientOption {connect .WithGRPC ()},
2347+ handler : func (responseWriter http.ResponseWriter , _ * http.Request ) {
2348+ header := responseWriter .Header ()
2349+ header .Set ("Content-Type" , "application/grpc" )
2350+ header .Set ("Grpc-Status" , "3" )
2351+ responseWriter .WriteHeader (http .StatusOK )
2352+ responseWriter .(http.Flusher ).Flush () //nolint:forcetypeassert
2353+ header .Set (http .TrailerPrefix + "Foo" , "abc" )
2354+ },
2355+ expectCode : connect .CodeInternal ,
2356+ expectMsg : "internal: corrupt response from server: gRPC trailers-only response may not contain HTTP trailers" ,
2357+ }, {
2358+ name : "grpc-web_trailers_after_trailers-only" ,
2359+ options : []connect.ClientOption {connect .WithGRPCWeb ()},
2360+ handler : func (responseWriter http.ResponseWriter , _ * http.Request ) {
2361+ header := responseWriter .Header ()
2362+ header .Set ("Content-Type" , "application/grpc-web" )
2363+ header .Set ("Grpc-Status" , "3" )
2364+ responseWriter .WriteHeader (http .StatusOK )
2365+ responseWriter .(http.Flusher ).Flush () //nolint:forcetypeassert
2366+ header .Set (http .TrailerPrefix + "Foo" , "abc" )
2367+ },
2368+ expectCode : connect .CodeInternal ,
2369+ expectMsg : "internal: corrupt response from server: gRPC trailers-only response may not contain HTTP trailers" ,
2370+ }}
2371+ for _ , testcase := range testcases {
2372+ testcase := testcase
2373+ t .Run (testcase .name , func (t * testing.T ) {
2374+ t .Parallel ()
2375+ mux := http .NewServeMux ()
2376+ mux .HandleFunc ("/" , func (responseWriter http.ResponseWriter , request * http.Request ) {
2377+ _ , _ = io .Copy (io .Discard , request .Body )
2378+ testcase .handler (responseWriter , request )
2379+ })
2380+ server := memhttptest .NewServer (t , mux )
2381+ client := pingv1connect .NewPingServiceClient (
2382+ server .Client (),
2383+ server .URL (),
2384+ testcase .options ... ,
2385+ )
2386+ const upTo = 2
2387+ request := connect .NewRequest (& pingv1.CountUpRequest {Number : upTo })
2388+ request .Header ().Set ("Test-Case" , t .Name ())
2389+ stream , err := client .CountUp (context .Background (), request )
2390+ assert .Nil (t , err )
2391+ for i := 0 ; stream .Receive () && i < upTo ; i ++ {
2392+ assert .Equal (t , stream .Msg ().GetNumber (), 42 )
2393+ }
2394+ assert .NotNil (t , stream .Err ())
2395+ assert .Equal (t , connect .CodeOf (stream .Err ()), testcase .expectCode )
2396+ assert .Equal (t , stream .Err ().Error (), testcase .expectMsg )
2397+ })
2398+ }
2399+ }
2400+
23102401// TestBlankImportCodeGeneration tests that services.connect.go is generated with
23112402// blank import statements to services.pb.go so that the service's Descriptor is
23122403// available in the global proto registry.
0 commit comments