From 0bbd5bda55653706aac4e00c4158b21575939898 Mon Sep 17 00:00:00 2001 From: Frank Mueller Date: Wed, 15 Dec 2021 23:26:53 +0100 Subject: [PATCH] Change and extend web body helpers (#16) * Change and extend web body helpers * Fix linter errors * Fix linter errors --- go.mod | 2 +- web/web.go | 26 +++++++++++++++++++----- web/web_test.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index ea73e8d..f428491 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module tideland.dev/go/audit -go 1.16 +go 1.17 diff --git a/web/web.go b/web/web.go index 542bb02..503e62f 100644 --- a/web/web.go +++ b/web/web.go @@ -70,18 +70,34 @@ func (w *ResponseWriter) finalize(r *http.Request) { } //-------------------- -// RESPONSE HELPER +// BODY HELPER //-------------------- -// BodyAsString reads the whole body and simply interprets it as string. -func BodyAsString(r *http.Response) (string, error) { +// StringToBody sets the request body to a given string. +func StringToBody(s string, r *http.Request) { + r.Body = ioutil.NopCloser(bytes.NewBufferString(s)) +} + +// JSONToBody sets the request body to the JSON representation of +// the given object. +func JSONToBody(obj interface{}, r *http.Request) error { + b := bytes.NewBuffer(nil) + if err := json.NewEncoder(b).Encode(obj); err != nil { + return err + } + r.Body = ioutil.NopCloser(b) + return nil +} + +// BodyToString reads the whole body and simply interprets it as string. +func BodyToString(r *http.Response) (string, error) { bs, err := ioutil.ReadAll(r.Body) return string(bs), err } -// BodyAsJSON reads the whole body and decodes the JSON content into the +// BodyToJSON reads the whole body and decodes the JSON content into the // given object. -func BodyAsJSON(r *http.Response, obj interface{}) error { +func BodyToJSON(r *http.Response, obj interface{}) error { return json.NewDecoder(r.Body).Decode(obj) } diff --git a/web/web_test.go b/web/web_test.go index 81106b8..4617372 100644 --- a/web/web_test.go +++ b/web/web_test.go @@ -51,12 +51,54 @@ func TestSimpleRequests(t *testing.T) { resp, err := s.Do(req) assert.NoError(err) assert.Equal(resp.StatusCode, http.StatusOK) - body, err := web.BodyAsString(resp) + body, err := web.BodyToString(resp) assert.NoError(err) assert.Equal(body, test.expected) } } +// TestJSONBody verifies the reading and writing of JSON bodies. +func TestJSONBody(t *testing.T) { + assert := asserts.NewTesting(t, asserts.FailStop) + + // Correctly marshalling data. + s := web.NewFuncSimulator(func(w http.ResponseWriter, r *http.Request) { + b, err := ioutil.ReadAll(r.Body) + assert.NoError(err) + _, err = w.Write(b) + assert.NoError(err) + }) + req, err := http.NewRequest(http.MethodGet, "https://localhost:8080/", nil) + assert.NoError(err) + err = web.JSONToBody(data{"correct", 12345, true}, req) + assert.NoError(err) + resp, err := s.Do(req) + assert.NoError(err) + assert.Equal(resp.StatusCode, http.StatusOK) + var obj data + err = web.BodyToJSON(resp, &obj) + assert.NoError(err) + assert.Equal(obj.A, "correct") + assert.Equal(obj.B, 12345) + assert.Equal(obj.C, true) + + // Failing marshalling data. + s = web.NewFuncSimulator(func(w http.ResponseWriter, r *http.Request) { + _, err := w.Write([]byte("{xyz)[]")) + assert.NoError(err) + }) + req, err = http.NewRequest(http.MethodGet, "https://localhost:8080/", nil) + assert.NoError(err) + err = web.JSONToBody(data{"correct", 12345, true}, req) + assert.NoError(err) + resp, err = s.Do(req) + assert.NoError(err) + assert.Equal(resp.StatusCode, http.StatusOK) + err = web.BodyToJSON(resp, &obj) + assert.ErrorContains(err, "invalid character") + +} + // TestResponseCode verifies that the status code cannot be changed after // writing to the response body. func TestResponseCode(t *testing.T) { @@ -120,7 +162,7 @@ func TestPreprocessors(t *testing.T) { resp, err := s.Do(req) assert.NoError(err) assert.Equal(resp.StatusCode, http.StatusOK) - body, err := web.BodyAsString(resp) + body, err := web.BodyToString(resp) assert.NoError(err) assert.Equal(body, test.expected) } @@ -156,4 +198,11 @@ func (h *echoHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "m(%s) p(%s) ct(%s) a(%s) b(%s)", m, p, ct, a, string(bs)) } +// data is used when testing the JSON marshalling. +type data struct { + A string `json:"a"` + B int `json:"b"` + C bool `json:"c"` +} + // EOF