Repository: goadesign/goa
Pull request #3001 (2022-02-16 19:52:06)

Do not encode error if conn has been hijacked
This fixes https://github.com/goadesign/goa/issues/2775 following the suggestion made by @raphael [here](https://github.com/goadesign/goa/issues/2775#issuecomment-1037481702).

raphael: Looks great, thank you!

Patch:
diff --git a/http/codegen/server.go b/http/codegen/server.go
index 4e889437..f6a6d17d 100644
--- a/http/codegen/server.go
+++ b/http/codegen/server.go
@@ -495,7 +495,9 @@ func {{ .HandlerInit }}(
 	{{- if not .Redirect }}
 		if err != nil {
 			{{- if isWebSocketEndpoint . }}
-			if _, ok := err.(websocket.HandshakeError); ok {
+			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+				// Response writer has been hijacked, do not encode the error
+				errhandler(ctx, w, err)
 				return
 			}
 			{{- end }}


Test patch:
diff --git a/http/codegen/testdata/streaming_code.go b/http/codegen/testdata/streaming_code.go
index 136e7343..395f2047 100644
--- a/http/codegen/testdata/streaming_code.go
+++ b/http/codegen/testdata/streaming_code.go
@@ -58,7 +58,9 @@ func NewStreamingResultMethodHandler(
 		}
 		_, err = endpoint(ctx, v)
 		if err != nil {
-			if _, ok := err.(websocket.HandshakeError); ok {
+			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+				// Response writer has been hijacked, do not encode the error
+				errhandler(ctx, w, err)
 				return
 			}
 			if err := encodeError(ctx, w, err); err != nil {
@@ -193,7 +195,9 @@ func NewStreamingResultNoPayloadMethodHandler(
 		}
 		_, err = endpoint(ctx, v)
 		if err != nil {
-			if _, ok := err.(websocket.HandshakeError); ok {
+			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+				// Response writer has been hijacked, do not encode the error
+				errhandler(ctx, w, err)
 				return
 			}
 			if err := encodeError(ctx, w, err); err != nil {
@@ -939,7 +943,9 @@ func NewStreamingPayloadMethodHandler(
 		}
 		_, err = endpoint(ctx, v)
 		if err != nil {
-			if _, ok := err.(websocket.HandshakeError); ok {
+			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+				// Response writer has been hijacked, do not encode the error
+				errhandler(ctx, w, err)
 				return
 			}
 			if err := encodeError(ctx, w, err); err != nil {
@@ -1100,7 +1106,9 @@ func NewStreamingPayloadNoPayloadMethodHandler(
 		}
 		_, err = endpoint(ctx, v)
 		if err != nil {
-			if _, ok := err.(websocket.HandshakeError); ok {
+			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+				// Response writer has been hijacked, do not encode the error
+				errhandler(ctx, w, err)
 				return
 			}
 			if err := encodeError(ctx, w, err); err != nil {
@@ -2085,7 +2093,9 @@ func NewBidirectionalStreamingMethodHandler(
 		}
 		_, err = endpoint(ctx, v)
 		if err != nil {
-			if _, ok := err.(websocket.HandshakeError); ok {
+			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+				// Response writer has been hijacked, do not encode the error
+				errhandler(ctx, w, err)
 				return
 			}
 			if err := encodeError(ctx, w, err); err != nil {
@@ -2287,7 +2297,9 @@ func NewBidirectionalStreamingNoPayloadMethodHandler(
 		}
 		_, err = endpoint(ctx, v)
 		if err != nil {
-			if _, ok := err.(websocket.HandshakeError); ok {
+			if _, werr := w.Write(nil); werr == http.ErrHijacked {
+				// Response writer has been hijacked, do not encode the error
+				errhandler(ctx, w, err)
 				return
 			}
 			if err := encodeError(ctx, w, err); err != nil {