From 63cd125327978a99085b829325c69faf41ab0ee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Abdelkader=20Mart=C3=ADnez=20P=C3=A9rez?= Date: Mon, 21 Oct 2019 10:25:34 +0200 Subject: [PATCH] Implement setResponseBody Co-authored-by: Hector Hurtado --- internal/server/data/resource.go | 9 ++++ internal/server/data/resource_test.go | 67 +++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/internal/server/data/resource.go b/internal/server/data/resource.go index 609ad54..37c81b2 100644 --- a/internal/server/data/resource.go +++ b/internal/server/data/resource.go @@ -172,3 +172,12 @@ func setResponseCookies(w http.ResponseWriter, r *http.Request, h *model.Handler c := &http.Cookie{Name: name, Value: string(vb)} http.SetCookie(h.Writer, c) } + +func setResponseBody(w http.ResponseWriter, r *http.Request, h *model.Handler) { + if n, err := io.Copy(h.Writer, r.Body); err != nil { + if n > 0 { + panic("Truncated body") + } + w.WriteHeader(http.StatusInternalServerError) + } +} diff --git a/internal/server/data/resource_test.go b/internal/server/data/resource_test.go index 207e3f2..7546dbd 100644 --- a/internal/server/data/resource_test.go +++ b/internal/server/data/resource_test.go @@ -1262,3 +1262,70 @@ func TestSetResponseCookiesAddsValueToExistingCookie(t *testing.T) { } // TODO: Validate Cookie Name&Value encoding + +func TestSetResponseBody200sOnHappyPath(t *testing.T) { + h := model.Handler{ + Request: httptest.NewRequest("POST", "/", nil), + Writer: httptest.NewRecorder(), + } + r := httptest.NewRequest("PUT", "/", nil) + w := httptest.NewRecorder() + + setResponseBody(w, r, &h) + + res := w.Result() + if res.StatusCode != http.StatusOK { + t.Errorf("Status code mismatch. Expected: 200, Got: %d", res.StatusCode) + } +} + +func TestSetResponseBodySetsTheResponseBody(t *testing.T) { + hw := httptest.NewRecorder() + h := model.Handler{ + Request: httptest.NewRequest("POST", "/", nil), + Writer: hw, + } + r := createMuxRequest("/handlers/HANDLERID/response/body", "/handlers/HANDLERID/response/body", "PUT", strings.NewReader("BAZ")) + w := httptest.NewRecorder() + + setResponseBody(w, r, &h) + + res := hw.Result() + if body, _ := ioutil.ReadAll(res.Body); string(body) != "BAZ" { + t.Errorf(`Body mismatch. Expected: "BAZ". Got: %q`, string(body)) + } +} + +func TestSetResponseBody500sWhenReaderFailsInFirstRead(t *testing.T) { + hw := httptest.NewRecorder() + h := model.Handler{ + Request: httptest.NewRequest("POST", "/", nil), + Writer: hw, + } + r := createMuxRequest("/handlers/HANDLERID/response/body", "/handlers/HANDLERID/response/body", "PUT", BadReader("Fail by design")) + w := httptest.NewRecorder() + + setResponseBody(w, r, &h) + + res := w.Result() + if res.StatusCode != http.StatusInternalServerError { + t.Errorf("Status code mismatch. Expected: 500, Got: %d", res.StatusCode) + } +} + +func TestSetResponseBodyPanicsIfReaderFailsAfterFirstWrite(t *testing.T) { + hw := httptest.NewRecorder() + h := model.Handler{ + Request: httptest.NewRequest("POST", "/", nil), + Writer: hw, + } + r := createMuxRequest("/handlers/HANDLERID/response/body", "/handlers/HANDLERID/response/body", "PUT", ErrorOnSecondReadReader(strings.NewReader("FOO"))) + w := httptest.NewRecorder() + + defer func() { + if rec := recover(); rec == nil { + t.Error("Didn't panic") + } + }() + setResponseBody(w, r, &h) +}