From 47cbddbd2792d3bfad3e33371cf3cb2b97d7cff8 Mon Sep 17 00:00:00 2001 From: Kyle Reynolds Date: Fri, 5 Apr 2024 14:06:41 -0600 Subject: [PATCH] fs rc: fixes incorrect Content-Type in HTTP API - fixes #7726 --- fs/rc/rcserver/rcserver.go | 2 ++ fs/rc/rcserver/rcserver_test.go | 53 ++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/fs/rc/rcserver/rcserver.go b/fs/rc/rcserver/rcserver.go index 21378e8ec..ae355a757 100644 --- a/fs/rc/rcserver/rcserver.go +++ b/fs/rc/rcserver/rcserver.go @@ -200,6 +200,7 @@ func (s *Server) Serve() error { func writeError(path string, in rc.Params, w http.ResponseWriter, err error, status int) { fs.Errorf(nil, "rc: %q: error: %v", path, err) params, status := rc.Error(path, in, err, status) + w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) err = rc.WriteJSON(w, params) if err != nil { @@ -294,6 +295,7 @@ func (s *Server) handlePost(w http.ResponseWriter, r *http.Request, path string) } fs.Debugf(nil, "rc: %q: reply %+v: %v", path, out, err) + w.Header().Set("Content-Type", "application/json") err = rc.WriteJSON(w, out) if err != nil { // can't return the error at this point - but have a go anyway diff --git a/fs/rc/rcserver/rcserver_test.go b/fs/rc/rcserver/rcserver_test.go index 47ec89e58..66009becd 100644 --- a/fs/rc/rcserver/rcserver_test.go +++ b/fs/rc/rcserver/rcserver_test.go @@ -3,6 +3,7 @@ package rcserver import ( "bytes" "context" + "encoding/json" "fmt" "io" "net/http" @@ -147,7 +148,11 @@ func testServer(t *testing.T, tests []testRun, opt *rc.Options) { body, err := io.ReadAll(resp.Body) require.NoError(t, err) - if test.Contains == nil { + if test.ContentType == "application/json" && test.Expected != "" { + expectedNormalized := normalizeJSON(t, test.Expected) + actualNormalized := normalizeJSON(t, string(body)) + assert.Equal(t, expectedNormalized, actualNormalized, "Normalized JSON does not match") + } else if test.Contains == nil { assert.Equal(t, test.Expected, string(body)) } else { assert.True(t, test.Contains.Match(body), fmt.Sprintf("body didn't match: %v: %v", test.Contains, string(body))) @@ -847,3 +852,49 @@ func TestServeModTime(t *testing.T) { }} testServer(t, tests, &opt) } + +func TestContentTypeJSON(t *testing.T) { + tests := []testRun{ + { + Name: "Check Content-Type for JSON response", + URL: "rc/noop", + Method: "POST", + Body: `{}`, + ContentType: "application/json", + Status: http.StatusOK, + Expected: "{}\n", + Headers: map[string]string{ + "Content-Type": "application/json", + }, + }, + { + Name: "Check Content-Type for JSON error response", + URL: "rc/error", + Method: "POST", + Body: `{}`, + ContentType: "application/json", + Status: http.StatusInternalServerError, + Expected: `{ + "error": "arbitrary error on input map[]", + "input": {}, + "path": "rc/error", + "status": 500 + } + `, + Headers: map[string]string{ + "Content-Type": "application/json", + }, + }, + } + opt := newTestOpt() + testServer(t, tests, &opt) +} + +func normalizeJSON(t *testing.T, jsonStr string) string { + var jsonObj map[string]interface{} + err := json.Unmarshal([]byte(jsonStr), &jsonObj) + require.NoError(t, err, "JSON unmarshalling failed") + normalizedJSON, err := json.Marshal(jsonObj) + require.NoError(t, err, "JSON marshalling failed") + return string(normalizedJSON) +}