From 8c8f92fd6ccb8ab05d4df36f76f79eaf9014f068 Mon Sep 17 00:00:00 2001 From: Wes Date: Wed, 31 Jan 2024 08:50:19 -0700 Subject: [PATCH] feat: default response content type to json if not specified --- backend/controller/controller.go | 1 + backend/controller/ingress/ingress.go | 23 +++++++---- backend/controller/ingress/ingress_test.go | 46 ++++++++++++++++++++++ 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/backend/controller/controller.go b/backend/controller/controller.go index 92a30169f1..4e4dbfe95e 100644 --- a/backend/controller/controller.go +++ b/backend/controller/controller.go @@ -248,6 +248,7 @@ func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } + ingress.SetDefaultContentType(response.Headers) responseBody, err = ingress.ResponseBodyForContentType(response.Headers, response.Body) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/backend/controller/ingress/ingress.go b/backend/controller/ingress/ingress.go index ea8704c54a..e5c2f073c0 100644 --- a/backend/controller/ingress/ingress.go +++ b/backend/controller/ingress/ingress.go @@ -61,17 +61,24 @@ func matchSegments(pattern, urlPath string, onMatch func(segment, value string)) return true } -func ResponseBodyForContentType(headers map[string][]string, body []byte) ([]byte, error) { - contentType, hasContentType := headers["Content-Type"] - if !hasContentType || len(contentType) == 0 || contentType[0] == "" || !strings.HasPrefix(contentType[0], "text/") { - return body, nil +func SetDefaultContentType(headers map[string][]string) { + if _, hasContentType := headers["Content-Type"]; !hasContentType { + headers["Content-Type"] = []string{"application/json"} } +} - var htmlContent string - if err := json.Unmarshal(body, &htmlContent); err != nil { - return nil, err +func ResponseBodyForContentType(headers map[string][]string, body []byte) ([]byte, error) { + if contentType, hasContentType := headers["Content-Type"]; hasContentType { + if strings.HasPrefix(contentType[0], "text/") { + var textContent string + if err := json.Unmarshal(body, &textContent); err != nil { + return nil, err + } + return []byte(textContent), nil + } } - return []byte(htmlContent), nil + + return body, nil } func ValidateCallBody(body []byte, verbRef *schema.VerbRef, sch *schema.Schema) error { diff --git a/backend/controller/ingress/ingress_test.go b/backend/controller/ingress/ingress_test.go index f2a54c67e0..a7efe487f2 100644 --- a/backend/controller/ingress/ingress_test.go +++ b/backend/controller/ingress/ingress_test.go @@ -140,3 +140,49 @@ func TestParseQueryJson(t *testing.T) { assert.Equal(t, test.request, actual, test.query) } } + +func TestSetDefaultContentType(t *testing.T) { + headers := map[string][]string{} + SetDefaultContentType(headers) + assert.Equal(t, map[string][]string{"Content-Type": {"application/json"}}, headers) + + headers = map[string][]string{"Content-Type": {"text/html"}} + SetDefaultContentType(headers) + assert.Equal(t, map[string][]string{"Content-Type": {"text/html"}}, headers) +} + +func TestResponseBodyForContentType(t *testing.T) { + tests := []struct { + name string + headers map[string][]string + body []byte + expectedBody []byte + }{ + { + name: "application/json", + headers: map[string][]string{"Content-Type": {"application/json"}}, + body: []byte(`{"message": "Hello, World!"}`), + expectedBody: []byte(`{"message": "Hello, World!"}`), + }, + { + name: "text/html", + headers: map[string][]string{"Content-Type": {"text/html"}}, + body: []byte(`"Hello, World!"`), + expectedBody: []byte("Hello, World!"), + }, + { + name: "Default to application/json", + headers: map[string][]string{}, + body: []byte(`{"message": "Default to JSON"}`), + expectedBody: []byte(`{"message": "Default to JSON"}`), + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + result, err := ResponseBodyForContentType(tc.headers, tc.body) + assert.NoError(t, err) + assert.Equal(t, tc.expectedBody, result) + }) + } +}