Repository: goadesign/goa (go)

Issue:
Streaming: can't encode error
We noticed some change in behavior with https://github.com/goadesign/goa/pull/3001, if no results are streamed back but an error is returned, Goa is unable to encode it correctly.

It seems to be due to the new call to `w.Write(nil)`, which unfortunately has a side-effect of writing out the "200 OK" status code.

So for the non-`http.ErrHijacked` cases, the subsequent call to `encodeError` will not be able to write out the correct status code.

Pull request description:
Fix returning correct status code on not hijacked streaming endpoints
Fixes #3054

Patch:
diff --git a/http/codegen/server.go b/http/codegen/server.go
index e26c5e9a..a091e69c 100644
--- a/http/codegen/server.go
+++ b/http/codegen/server.go
@@ -496,7 +496,7 @@ func {{ .HandlerInit }}(
 	{{- if not .Redirect }}
 		if err != nil {
 			{{- if isWebSocketEndpoint . }}
-			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+			if v.Stream.(*{{ .ServerWebSocket.VarName }}).conn != nil {
 				// Response writer has been hijacked, do not encode the error
 				errhandler(ctx, w, err)
 				return


Test patch:
diff --git a/http/codegen/testdata/streaming_code.go b/http/codegen/testdata/streaming_code.go
index b075ca6e..003bbcd4 100644
--- a/http/codegen/testdata/streaming_code.go
+++ b/http/codegen/testdata/streaming_code.go
@@ -58,7 +58,7 @@ func NewStreamingResultMethodHandler(
 		}
 		_, err = endpoint(ctx, v)
 		if err != nil {
-			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+			if v.Stream.(*StreamingResultMethodServerStream).conn != nil {
 				// Response writer has been hijacked, do not encode the error
 				errhandler(ctx, w, err)
 				return
@@ -195,7 +195,7 @@ func NewStreamingResultNoPayloadMethodHandler(
 		}
 		_, err = endpoint(ctx, v)
 		if err != nil {
-			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+			if v.Stream.(*StreamingResultNoPayloadMethodServerStream).conn != nil {
 				// Response writer has been hijacked, do not encode the error
 				errhandler(ctx, w, err)
 				return
@@ -943,7 +943,7 @@ func NewStreamingPayloadMethodHandler(
 		}
 		_, err = endpoint(ctx, v)
 		if err != nil {
-			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+			if v.Stream.(*StreamingPayloadMethodServerStream).conn != nil {
 				// Response writer has been hijacked, do not encode the error
 				errhandler(ctx, w, err)
 				return
@@ -1104,7 +1104,7 @@ func NewStreamingPayloadNoPayloadMethodHandler(
 		}
 		_, err = endpoint(ctx, v)
 		if err != nil {
-			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+			if v.Stream.(*StreamingPayloadNoPayloadMethodServerStream).conn != nil {
 				// Response writer has been hijacked, do not encode the error
 				errhandler(ctx, w, err)
 				return
@@ -2089,7 +2089,7 @@ func NewBidirectionalStreamingMethodHandler(
 		}
 		_, err = endpoint(ctx, v)
 		if err != nil {
-			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+			if v.Stream.(*BidirectionalStreamingMethodServerStream).conn != nil {
 				// Response writer has been hijacked, do not encode the error
 				errhandler(ctx, w, err)
 				return
@@ -2291,7 +2291,7 @@ func NewBidirectionalStreamingNoPayloadMethodHandler(
 		}
 		_, err = endpoint(ctx, v)
 		if err != nil {
-			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+			if v.Stream.(*BidirectionalStreamingNoPayloadMethodServerStream).conn != nil {
 				// Response writer has been hijacked, do not encode the error
 				errhandler(ctx, w, err)
 				return