Repository: goadesign/goa
Pull request #2823 (2021-04-28 10:47:05)

Properly handle media types with params by http.ResponseEncoder()
* `http.ResponseEncoder` always returns `json.Encoder` if media type contains a param.
* This pull request fixes it.

raphael: Whoops, thank you!

Patch:
diff --git a/http/encoding.go b/http/encoding.go
index 57e63931..bf34904e 100644
--- a/http/encoding.go
+++ b/http/encoding.go
@@ -134,15 +134,15 @@ func ResponseEncoder(ctx context.Context, w http.ResponseWriter) Encoder {
 			// from the content type context key.
 			if mt, _, err = mime.ParseMediaType(ct); err == nil {
 				switch {
-				case ct == "application/json" || strings.HasSuffix(ct, "+json"):
+				case mt == "application/json" || strings.HasSuffix(mt, "+json"):
 					enc = json.NewEncoder(w)
-				case ct == "application/xml" || strings.HasSuffix(ct, "+xml"):
+				case mt == "application/xml" || strings.HasSuffix(mt, "+xml"):
 					enc = xml.NewEncoder(w)
-				case ct == "application/gob" || strings.HasSuffix(ct, "+gob"):
+				case mt == "application/gob" || strings.HasSuffix(mt, "+gob"):
 					enc = gob.NewEncoder(w)
-				case ct == "text/html" || ct == "text/plain" ||
-					strings.HasSuffix(ct, "+html") || strings.HasSuffix(ct, "+txt"):
-					enc = newTextEncoder(w, ct)
+				case mt == "text/html" || mt == "text/plain" ||
+					strings.HasSuffix(mt, "+html") || strings.HasSuffix(mt, "+txt"):
+					enc = newTextEncoder(w, mt)
 				default:
 					enc = json.NewEncoder(w)
 				}


Test patch:
diff --git a/http/encoding_test.go b/http/encoding_test.go
index 2dd21103..9272d07f 100644
--- a/http/encoding_test.go
+++ b/http/encoding_test.go
@@ -36,6 +36,21 @@ func TestResponseEncoder(t *testing.T) {
 		{"ct +html", "+html", "application/gob", "*http.textEncoder"},
 		{"ct plain", "text/plain", "application/gob", "*http.textEncoder"},
 		{"ct +txt", "+txt", "application/gob", "*http.textEncoder"},
+		{"no ct, at json with params", "", "application/json; charset=utf-8", "*json.Encoder"},
+		{"no ct, at xml with params", "", "application/xml; charset=utf-8", "*xml.Encoder"},
+		{"no ct, at gob with params", "", "application/gob; charset=utf-8", "*gob.Encoder"},
+		{"no ct, at html with params", "", "text/html; charset=utf-8", "*http.textEncoder"},
+		{"no ct, at plain with params", "", "text/plain; charset=utf-8", "*http.textEncoder"},
+		{"ct json with params", "application/json; charset=utf-8", "application/gob", "*json.Encoder"},
+		{"ct +json with params", "+json; charset=utf-8", "application/gob", "*json.Encoder"},
+		{"ct xml with params", "application/xml; charset=utf-8", "application/gob", "*xml.Encoder"},
+		{"ct +xml with params", "+xml; charset=utf-8", "application/gob", "*xml.Encoder"},
+		{"ct gob with params", "application/gob; charset=utf-8", "application/xml", "*gob.Encoder"},
+		{"ct +gob with params", "+gob; charset=utf-8", "application/xml", "*gob.Encoder"},
+		{"ct html with params", "text/html; charset=utf-8", "application/gob", "*http.textEncoder"},
+		{"ct +html with params", "+html; charset=utf-8", "application/gob", "*http.textEncoder"},
+		{"ct plain with params", "text/plain; charset=utf-8", "application/gob", "*http.textEncoder"},
+		{"ct +txt with params", "+txt; charset=utf-8", "application/gob", "*http.textEncoder"},
 	}
 
 	for _, c := range cases {