diff --git a/internal/server/data/resource.go b/internal/server/data/resource.go index 5116ec1..cb7a144 100644 --- a/internal/server/data/resource.go +++ b/internal/server/data/resource.go @@ -2,8 +2,10 @@ package data import ( "io" + "io/ioutil" "net/http" "net/textproto" + "strconv" "github.com/BBVA/kapow/internal/server/model" "github.com/gorilla/mux" @@ -123,3 +125,22 @@ func getRequestFileContent(w http.ResponseWriter, r *http.Request, h *model.Hand w.WriteHeader(http.StatusNotFound) } } + +// FIXME: Allow any HTTP status code. Now we are limited by WriteHeader +// capabilities +func getResponseStatus(w http.ResponseWriter, r *http.Request, h *model.Handler) { + sb, err := ioutil.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + si, err := strconv.Atoi(string(sb)) + if http.StatusText(si) == "" { + w.WriteHeader(http.StatusBadRequest) + } else if err == nil { + h.Writer.WriteHeader(int(si)) + } else { + w.WriteHeader(http.StatusBadRequest) + } +} diff --git a/internal/server/data/resource_test.go b/internal/server/data/resource_test.go index 362f4c3..6824ae1 100644 --- a/internal/server/data/resource_test.go +++ b/internal/server/data/resource_test.go @@ -999,3 +999,86 @@ func TestGetRequestFileContent500sWhenHandlerRequestErrors(t *testing.T) { t.Error("status not 500", res.StatusCode) } } + +func TestSetResponseStatus200sOnHappyPath(t *testing.T) { + h := model.Handler{ + Request: httptest.NewRequest("POST", "/", nil), + Writer: httptest.NewRecorder(), + } + r := httptest.NewRequest("PUT", "/", strings.NewReader("200")) + w := httptest.NewRecorder() + + getResponseStatus(w, r, &h) + + res := w.Result() + if res.StatusCode != http.StatusOK { + t.Errorf("Status code mismatch. Expected: 200, Got: %d", res.StatusCode) + } +} + +func TestSetResponseStatusSetsGivenStatus(t *testing.T) { + hw := httptest.NewRecorder() + h := model.Handler{ + Request: httptest.NewRequest("POST", "/", nil), + Writer: hw, + } + r := httptest.NewRequest("PUT", "/", strings.NewReader("418")) + w := httptest.NewRecorder() + + getResponseStatus(w, r, &h) + + res := hw.Result() + if res.StatusCode != http.StatusTeapot { + t.Errorf("Status code mismatch. Expected: 418, Got: %d", res.StatusCode) + } +} + +func TestSetResponseStatus400sWhenNonparseableStatusCode(t *testing.T) { + h := model.Handler{ + Request: httptest.NewRequest("POST", "/", nil), + Writer: httptest.NewRecorder(), + } + r := httptest.NewRequest("PUT", "/", strings.NewReader("foo")) + w := httptest.NewRecorder() + + getResponseStatus(w, r, &h) + + res := w.Result() + if res.StatusCode != http.StatusBadRequest { + t.Errorf("Status code mismatch. Expected: 400, Got: %d", res.StatusCode) + } +} + +func TestSetResponseStatus500sWhenErrorReadingRequest(t *testing.T) { + h := model.Handler{ + Request: httptest.NewRequest("POST", "/", nil), + Writer: httptest.NewRecorder(), + } + r := httptest.NewRequest("PUT", "/", BadReader("Failed by design")) + w := httptest.NewRecorder() + + getResponseStatus(w, r, &h) + + res := w.Result() + if res.StatusCode != http.StatusInternalServerError { + t.Errorf("Status code mismatch. Expected: 500, Got: %d", res.StatusCode) + } +} + +// FIXME: This is not the spec behavior but Go checks too many things to +// be sure. Discuss how to fix this. +func TestSetResponseStatus400sWhenStatusCodeNotSupportedByGo(t *testing.T) { + h := model.Handler{ + Request: httptest.NewRequest("POST", "/", nil), + Writer: httptest.NewRecorder(), + } + r := httptest.NewRequest("PUT", "/", strings.NewReader("99")) + w := httptest.NewRecorder() + + getResponseStatus(w, r, &h) + + res := w.Result() + if res.StatusCode != http.StatusBadRequest { + t.Errorf("Status code mismatch. Expected: 400, Got: %d", res.StatusCode) + } +}